Кодировка имен файлов в архивах zip

Материал из MediaWiki
Перейти к навигации Перейти к поиску

Довольно часто при открытии под Линуксом архивов, содержащих файлы и директории с кириллическими (и вообще любыми не-ASCII) названиями, обнаруживается, что имена файлов в них в неправильной кодировке. Если такой архив распаковать на диск, файлы на диске могут получиться с нечитаемыми названиями.

Происходит это потому, что в разных файловых системах имена файлов хранятся в разных кодировках, да ещё операционные системы работают с ними по-разному, а большинство архивных форматов не предусматривает указания кодировки: какая была при упаковке, такая и будет. Проще говоря, по историческим причинам в кодировках имён файлов в архивах царит кавардак.

Проблема чаще всего возникает с файлами формата ZIP, упакованными под Windows (вообще говоря, существует алгоритм правильного определения кодировок для таких архивов, но он мало где поддерживается). Собственно, форматы TAR, GZIP, BZIP2 и многие другие тоже этому подвержены, но они чаще всего создаются под Линуксом или на других POSIX-совместимых платформах, а там сейчас почти всегда одна и та же кодировка — UTF-8, поэтому проблема не проявляется.

Эта проблема касается исключительно имён файлов и директорий. Содержимого файлов это никак не касается. Естественно, если в архиве есть текстовый файл в неизвестной кодировке, вам придётся её подбирать в текстовом редакторе, но это уже совсем другая история.

Если надо распаковать такой архив, то решение очень простое: надо указать архиватору, в какой кодировке там имена файлов. Проблема в том, что распространённые архиваторы с графическим интерфейсом такой опции не имеют, программы для командной строки обычно тоже (в лучшем случае она глубоко спрятана в документации). Поэтому приводим советы, как именно нужно поступать.

Что касается самой кодировки, то стоит ожидать либо UTF-8, либо CP866, либо (редко) CP1251.

Разархиваторы, которые просто работают

far2l (linux порт Far Manager) выбирает кодировку не-юникодных архивов по системной локали — "сжатые папки" в Windows ведут себя точно также. ppa


The Unarchiver (в дистрибутивах - пакеты unar, unarchiver) умеет угадывать кодировку статистическими методами

unar file.zip

bsdtar (из состава libarchive) умеет распаковывать zip-файлы и преобразует кодировку имен на лету

bsdtar --option hdrcharset=cp866 -xf file.zip

Рецепт для Ubuntu

Добавляем репозиторий с исправленной версией архиваторов:

sudo add-apt-repository ppa:frol/zip-i18n

Обновляем репозитории и пакеты:

sudo apt-get update
sudo apt-get upgrade

Далее устанавливаем следующие пакеты:

sudo apt-get install p7zip p7zip-full

Теперь названия файлов в архивах будут отображаться в правильной кодировке.

Рецепт для Gentoo

После пересборки zip и unzip с USE-флагом natspec всё работает само собой. В любительском оверлее rusxmms доступен пакет p7zip с графическим интерфейсом для архиватора 7-Zip, в котором также поправлена кодировка. Для p7zip необходимо включить USE-флах rcc, который используется также в некоторых других пакетах данного оверлея, например id3tag и mpg123.

Рецепт для Fedora

Можно позаимствовать патчи unzip и libnatspec у проекта RussianFedora:

libnatspec

unzip

Рецепт для Archlinux

Установите пакет unzip-iconv с AUR:

yaourt -S unzip-iconv

Рецепт для openSUSE

#zypper in unzip-rcc

Универсальные решения

Актуальны для любого дистрибутива

Для терминала

ls | iconv -f Latin1 -t cp850 | iconv -f cp866
unzip file.zip -d directory-name
cd directory-name
convmv -f cp866 -t utf8 *
# удостоверяемся, что всё в порядке
convmv --notest -f cp866 -t utf8 *
# вместо cp866 может понадобиться cp1251 или даже koi8-r

Для Gnome 2

  1. Ставим fuse-zip
  1. Создаём директорию ~/.ZIP
  1. Пишем скрипт:
#! /bin/bash
fusermount -u ~/.ZIP
fuse-zip "$1" .ZIP -omodules=iconv,from_code=CP866,to_code=UTF8
nautilus ~/.ZIP
xrefresh -white
  1. Делаем исполняемым и помещаем например если стоит gnome в ~/.gnome2/nautilus-scripts
  1. Назначаем открывать ZIP-архивы с помощью этого скрипта

Как самому упаковывать файлы, чтобы не было проблем

Проблем не будет, если все имена файлов и директорий в архиве состоят исключительно из латинских букв, цифр, пробелов и базовой пунктуации, кроме слэша (/) — слэш в именах файлов под Линуксом недопустим. Если архив будут открывать под Windows, там запрещённых символов больше: <, >, :, ", /, \, |, ? и * [1]. Но их и под Линуксом не рекомендуется использовать в именах файлов, потому что в командной строке все эти символы имеют специальное значение.

А также проблем не будет с форматом 7z (архиватор p7zip для Линукс/POSIX, 7-Zip для Windows), ни под Линуксом, ни под другими системами: архиватор при упаковке автоматически перекодирует все имена файлов в UTF-8, а при распаковке перекодирует их в кодировку системной локали. Формат полностью свободный и с хорошим сжатием, поэтому им и рекомендуется пользоваться.

Обычно не бывает проблем и с популярным форматом RAR, так как там имена файлов кодируются всегда в UTF-16. Но, во-первых, он проприетарный: свободные архиваторы его более-менее поддерживают, но с некоторыми версиями формата не справляются. Во-вторых, поступают сообщения, что некоторые архиваторы для Линукса всё-таки и при работе с RAR запарывают кодировку. Рекомендуется пользоваться 7z.

Стоит отметить, что программа zip от Info-ZIP, использующаяся в большинстве дистрибутивов, с версии 3.0 при создании архивов сохраняет имена файлов одновременно в двух кодировках: в той, какая есть, и в UTF-8. Такой архив можно будет распаковать без проблем, а совместимость со старыми версиями архиваторов при этом не нарушается. Но это никак не помогает при распаковке архивов, созданных другими программами. На самом деле, даже спецификация формата ZIP включает пункт о том, что имена файлов должны кодироваться либо в CP437, либо в UTF-8, но разработчики архиваторов часто игнорируют этот пункт.