RomeoGolf

Пн 28 Март 2016

Tar и «неправильная» кодировка имен файлов

Возникла задача более-менее регулярного переноса большого объема мелких файлов с одного компьютера на другой. Копирование напрямую хоть по сети, хоть через внешний накопитель занимает неприличное время. Желательно эту подборку как-то упаковать. Можно даже совсем без сжатия.

Лирическое отступление
Подобная задача хорошо знакома тем, кто регулярно выполняет резервное копирование, но малознакома большинству средних пользователей, в том числе и мне. Однако ж бывают случаи и для нас, не-админов. Во-первых, я пользуюсь расширением ScrapBook для браузера Mozilla FireFox и регулярно переношу накопленную полезную информацию из сети на те компьютеры, которыми пользуюсь при отсутствии сети. Это ноутбук, который со мной обычно там, где интернетов нет в принципе, а раньше и комп на работе, где интернету нету по велению свыше, впрочем, теперь туда с флэшками нельзя. Во-вторых, это кэш замечательной программы SAS Планета, для тех же условий, например, на ноутбуке в путешествиях.

Для такой цели (с учетом некритичности сжатия данных) трудно придумать что-нибудь лучше инструмента, специально для этого дела разработанного — tar. На больших наборах мелких файлов он уверенно обгоняет предпочитаемый мной в виндах 7zip без сжатия. Только что загнал в два архива — tar и 7z — папку с кучей мелочи 1,2 Гб: 6:29 против 15:49 (минут:секунд). Причем в подборке gnuwin32 имеется реализация tar под винду, помимо кучи других вкусностей, которые в Linux есть «из коробки».

Однако tar имеет одну неприятную особенность. Ежели, к примеру, запаковать в 7zip кучку файлов с кириллическими именами в винде, они нормально, по-русски, распакуются в Linux. И, что характерно, наоборот. А то, что упаковано в tar, будет распаковано в другой системе с непонятным набором символов вместо имен. По крайней мере, если винда все еще XP.

Более того, если загнать в tar упомянутую кучку в XP, то она и в XP распакуется с неправильными именами.

Лирическое отступление
Непосредственно для данных ScrapBook и тайлов SAS Планеты это не проблема, там нет кириллицы в именах файлов. Однако при экспорте пачки файлов из ScrapBook они сохраняются в папках, у которых имена совпадают с заголовком страницы, а это может быть и кириллица. Да и вообще, случаи разные бывают… Если есть проблема, хотелось бы иметь наготове способ решения.

Поиском по сети наткнулся на блог, автор которого предложил решение, основанное на ответе на superuser.com, а конкретно здесь.

Решение требует Python, он у меня есть, третий. Точнее, 3.3, потому что на одном из компьютеров, которыми я пользуюсь, стоит WinXP, а там версия 3.3 — последнее, что можно установить. На домашней семерке то же самое, чтобы не было путаницы при переносе кода.

Сперва я попробовал запустить предложенный скрипт не думая, просто скопировал код в py-файл и запустил. Ну, конечно, не получилось. Сперва была ошибка, связанная с тем, что в третьем питоне функция print — именно функция и требует скобочек, а потом мне в консоли сказали, что не знают такую фигню, как unicode().

Давненько я не общался с питонами, полез в справку. Что делать с unicode(), я так и не нашел, зато нашел справку по tarfile и обнаружил, что среди аргументов он принимает еще и encoding. И скрипт сразу упростился:

#!/usr/bin/python3

import tarfile
import sys

if len(sys.argv) == 1:
    print("usage: %s <tar archive>" % (sys.argv[0]))
    sys.exit(0)

arhive_name = sys.argv[1]

archive_encoding = 'cp1251'
#archive_encoding = 'utf-8'

tar = tarfile.open(name=arhive_name, mode='r', bufsize=16*1024, encoding=archive_encoding)
tar.extractall()
tar.close()

Запускается в винде с именем архива в аргументе: python <имя скрипта>.py <имя архива>.tar.

archive_encoding = 'cp1251' для распаковки (в винде и линуксе) таров, упакованных в винде, archive_encoding = 'utf-8' для распаковки в винде упакованных в Linux. Распаковывается с русскими именами файлов. Попробовал в Linux — тоже работает. Упакованные в Windows тары при открытии, скажем, в mc или распакованные через tar имеют битую кириллическую кодировку, а этим скриптом открываются нормально.

Кстати, если py-скрипт написан в Windows, то для запуска его в Linux нужно не забыть сменить формат файла на юниксовый, в смысле символов конца строки/возврата каретки. GVIM делает это очень просто: :set fileformat=unix.

Надо сказать, что Archive Manager (кажется, он в Debian Jessi работает архивариусом по умолчанию) открывает tar-архивы с правильной кодировкой, даже запакованные в Windows, а в винде 7zip открывает упакованное под линем тоже нормально. Но tar, даже в питоновом варианте, работает побыстрее, как мне показалось. Честно говоря, тут время я не засекал. Кроме того, 7zip в Windows коряво распаковывает tar-архивы с кириллическими именами, запакованными в этой же системе.

Я понимаю, что под задачу надо подбирать инструмент, требующий минимум извращений и издевательств, но случаи бывают разные. Например, тяжелое наследие прошлого или чужие данные, на подготовку которых уже повлиять нельзя, а использовать надо.


Теги: