Крякозябры ZIP (в какой они кодировке? :))
Модератор: Модераторы разделов
-
- Сообщения: 1445
- ОС: Debian Squeeze
Крякозябры ZIP
Вечная проблема неудобство: при распаковке zip-ов с файлами с русскими названиями файлов получаются крякозябры. Сначала боролся при помощи WinRAR. Теперь решил сделать по-человечески - написать скрипт, который бы переименовывал правильно.
В какой кодировке имена файлов в зипах? Судя по выводу ls | iconv -f cp1251, там не cp1251.
В какой кодировке имена файлов в зипах? Судя по выводу ls | iconv -f cp1251, там не cp1251.
-
- Сообщения: 43
- ОС: Debian testing
Re: Крякозябры ZIP
Как-то раньше это уже обсуждалось на этом форуме... Вот тут.
По мотивам обсуждения я записал себе в склерозник такой однострочник:
Не самый оптимальный вариант, но работающий (на тех архивах, что мне попадались). Восстанавливает только имена файлов, не каталогов (ибо такие архивы мне не попадались пока :)).
edit: Работает для файлов, распакованных 7-zip`ом.
upd:
Похоже однострочник работал на архивах по почте принятых, ибо создал сейчас в виртуалке zip ТоталКоммандером и получил кукиш при попытке востановить покоцаные unzip'ом имена файлов. 7-zip тоже чудит...
unzip версии 6.0-4
p7zip версии 9.04~dfsg.1-1
По мотивам обсуждения я записал себе в склерозник такой однострочник:
Код: Выделить всё
cd <каталог_куда_распакован_архив_с_битыми_именами_файлов> && find . -type f | while read f; do fnew=`echo "$f" | iconv -t iso8859-1 | iconv -f cp866`; echo "\"$f\" -> \"$fnew\""; mv -T "$f" "$fnew"; done
Не самый оптимальный вариант, но работающий (на тех архивах, что мне попадались). Восстанавливает только имена файлов, не каталогов (ибо такие архивы мне не попадались пока :)).
edit: Работает для файлов, распакованных 7-zip`ом.
upd:
Похоже однострочник работал на архивах по почте принятых, ибо создал сейчас в виртуалке zip ТоталКоммандером и получил кукиш при попытке востановить покоцаные unzip'ом имена файлов. 7-zip тоже чудит...
unzip версии 6.0-4
p7zip версии 9.04~dfsg.1-1
-
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Крякозябры ZIP
У меня 7z распаковывает в нормальной кодировке (возможно, iconv или enca в него включены).
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка

-
- Сообщения: 1445
- ОС: Debian Squeeze
Re: Крякозябры ZIP
Не работает. Пишет ошибки:
Код: Выделить всё
iconv: недопустимая входная последовательность в позиции 2
<крякозябры>
И понятно почему: вы пытаетесь преобразовать крякозябры в iso8859-1 (это Latin-1) (iconv -t iso8859-1), а соответствующих символов там нет.
У меня если указана локаль ru_UA.UTF-8, то 7z генерит крякозябры, которые мне так и не удалось обработать. Если указана любая не-юникодная, то имена в cp866.
А обычный unzip генерит что-то странное: пробовал преобразовывать полученное из любой известной мне русской кодировки и ничего вразумительного не получилось.
-
- Сообщения: 43
- ОС: Debian testing
Re: Крякозябры ZIP
Как вариант, можно использовать такое преобразование (на всякий случай прицепил архивчик, на котором оно работает):
Первый вариант раньше, видимо, работал. Почему — х.з. Видимо такой зип был. Решение было буквально вымучано на один или два вечера...
Хотелось бы и для 7-zip подобрать решение...
Код: Выделить всё
iconv -f cp1252 -t cp850 | iconv -f cp866
Первый вариант раньше, видимо, работал. Почему — х.з. Видимо такой зип был. Решение было буквально вымучано на один или два вечера...
Хотелось бы и для 7-zip подобрать решение...
У вас нет необходимых прав для просмотра вложений в этом сообщении.
-
- Сообщения: 1445
- ОС: Debian Squeeze
Re: Крякозябры ZIP
Спасибо, разобрался.
unzip -Z1 filename.zip | iconv -f cp1252 -t cp850 | iconv -f cp866
Этот однострочник позволяет посмотреть список файлов.
PS. Запилил свою переименовалку на AWK + простенький BASH-скрипт в качестве запускалки awk с нужными параметрами (пока, правда, не умеет работать с папками).
-
- Сообщения: 43
- ОС: Debian testing
Re: Крякозябры ZIP
Грабли на этом не заканчиваются.
Вот ещё один зип, с теми же файлами, только созданый средствами Windows XP — iconv -f cp1252 -t cp850 | iconv -f cp866 уже не работает...
frp,
А скрипт этот сразу переименовывает или для начала просто показывает что будет в итоге? Первый вариант чреват последствиями может быть...
upd:
Нашёл откуда conv -t iso8859-1 | iconv -f cp866 взялся.
Таким образом приводятся в порядок имена файлов при распаковке этих злосчастных зипов при помощи 7-zip. Причём имена восстанавливает в обоих случаях (в обоих архивах, вышеприцепленный 1.zip и 2xp.zip из этого сообщения).
upd2:
frp,
для скрипта может сгодится:
Zip-архив, созданный с помощью 7-Zip (win32) тоже после unzip не может востановить имена с помощью iconv -f cp1252 -t cp850 | iconv -f cp866
Вот ещё один зип, с теми же файлами, только созданый средствами Windows XP — iconv -f cp1252 -t cp850 | iconv -f cp866 уже не работает...
frp,
А скрипт этот сразу переименовывает или для начала просто показывает что будет в итоге? Первый вариант чреват последствиями может быть...
upd:
Нашёл откуда conv -t iso8859-1 | iconv -f cp866 взялся.
Таким образом приводятся в порядок имена файлов при распаковке этих злосчастных зипов при помощи 7-zip. Причём имена восстанавливает в обоих случаях (в обоих архивах, вышеприцепленный 1.zip и 2xp.zip из этого сообщения).
upd2:
frp,
для скрипта может сгодится:
Код: Выделить всё
$ hexdump -n 8 -C архив_созданный_totalcommander.zip
00000000 50 4b 03 04 14 00 02 00 |PK......|
$ hexdump -n 8 -C архив_созданный_winxp.zip
00000000 50 4b 03 04 0a 00 00 00 |PK......|
$ hexdump -n 8 -C 7zip_windows.zip
00000000 50 4b 03 04 14 00 00 00 |PK......|
Zip-архив, созданный с помощью 7-Zip (win32) тоже после unzip не может востановить имена с помощью iconv -f cp1252 -t cp850 | iconv -f cp866
У вас нет необходимых прав для просмотра вложений в этом сообщении.
-
- Сообщения: 1445
- ОС: Debian Squeeze
Re: Крякозябры ZIP
iglezz
В приведенном вами архиве имена просто в cp866, без особых извращений.
Интересно, а как, скажем, WinRAR, или хотя бы дефолтный виндовый архиватор (если его можно так обозвать), определяют, в какой там кодировке имена файлов?
PS. Можете еще поискать архивы, на которых подобные методы не прокатывают?
-
- Сообщения: 355
- ОС: Gentoo
Re: Крякозябры ZIP
У меня для получения имён файлов в обоих архивах прокатывало такое:
Распаковывать не пробовал. Вот что говорит enca:
(Created by format.vim)
LANG=C 7z l $ARCHIVE | enconv
Распаковывать не пробовал. Вот что говорит enca:
/tmp/zsh - 1 (Created by format.vim)
(zyx:~/tmp) % LANG=C 7z l 1.ZIP | enca
IBM/MS code page 866
LF line terminators
(zyx:~/tmp) % LANG=C 7z l 2xp.zip | enca
IBM/MS code page 866
LF line terminators
-
- Сообщения: 43
- ОС: Debian testing
-
- Администратор
- Сообщения: 5403
- ОС: Gentoo
Re: Крякозябры ZIP
app-arch/unzip и русский в именах файлов
Писал когда-то патч, добавляющий в unzip нормальную перекодировку. Версия 5.52, но, думаю, переделать по аналогии современную версию будет несложно.
Чуть ниже поста, на который я дал ссылку, приводится альтернативный патч, который в теории должен подходить к любой версии, но я его не проверял.
Писал когда-то патч, добавляющий в unzip нормальную перекодировку. Версия 5.52, но, думаю, переделать по аналогии современную версию будет несложно.
Чуть ниже поста, на который я дал ссылку, приводится альтернативный патч, который в теории должен подходить к любой версии, но я его не проверял.
-
- Сообщения: 1445
- ОС: Debian Squeeze
Re: Крякозябры ZIP
ZyX
Буду использовать 7z, кодировка одна на выходе получается, в отличии от unzip.
/dev/random
А вы не пробовали отправить ваш патч разработчикам unzip?
Как будет время, попробую адаптировать его для более новой версии и собрать debian-пакет.
Буду использовать 7z, кодировка одна на выходе получается, в отличии от unzip.
/dev/random
А вы не пробовали отправить ваш патч разработчикам unzip?
Как будет время, попробую адаптировать его для более новой версии и собрать debian-пакет.
-
- Сообщения: 3321
- Статус: Красный глаз тролля
- ОС: ArchLinux
Re: Крякозябры ZIP
А зачем нужен unzip сам по себе, если 7z вызывает его же, но через iconv или enca? У меня, например, никогда не было проблем с кодировками файлов, разархивируемых 7z (хоть из зипа, хоть из рара). А вот сами unzip и unrar отдают файлы в той же кодировке, в какой их записывали.
RTFM
-------
KOI8-R - патриотичная кодировка
-------
KOI8-R - патриотичная кодировка

-
- Сообщения: 355
- ОС: Gentoo
Re: Крякозябры ZIP
eddy писал(а): ↑20.01.2011 21:26
А зачем нужен unzip сам по себе, если 7z вызывает его же, но через iconv или enca? У меня, например, никогда не было проблем с кодировками файлов, разархивируемых 7z (хоть из зипа, хоть из рара). А вот сами unzip и unrar отдают файлы в той же кодировке, в какой их записывали.
Доказательства?
~/tmp/image/p7zip_9.13/zsh - 1 (Created by format.vim)
(zyx:tmp/image/p7zip_9.13) % grep -r -i -w unzip . -C 10
./ChangeLog-
./ChangeLog-Version 4.56 (never published)
./ChangeLog-============
./ChangeLog- - From Windows version of 7-zip 4.56 :
./ChangeLog- - Some bugs were fixed
./ChangeLog-
./ChangeLog- - On HPUX : fixed "Can't load '../bin/7z.dll'"
./ChangeLog- (Unsatisfied data symbol '_ZTVN10__cxxabiv121__vmi_class_type_infoE' in load module '../bin/7z.so'.)
./ChangeLog-
./ChangeLog- - bug : p7zip used to build a zip file with an "FAT" header instead of "Unix" header
./ChangeLog: If LANG was set, "unzip" tried to translate the filenames from "FAT" to locale ...
./ChangeLog-
./ChangeLog- - On AIX : fixed "HugeFiles=off" (thank kuriath)
./ChangeLog-
./ChangeLog- - bug #1800180 : LZMAlone compilation error in COutFile
./ChangeLog-
./ChangeLog- - Patch #1796569 : Fix FreeBSD FTBFS
./ChangeLog-
./ChangeLog- - Patch #1796575 : fix man1/7za.1 man1/7zr.1 man1/7z.1
./ChangeLog-
./ChangeLog-
(zyx:tmp/image/p7zip_9.13) %
Это единственное упоминание unzip в коде 7-zip.
-
- Сообщения: 539
- ОС: Ubuntu 10.04 with OpenBox
Re: Крякозябры ZIP
Кстати, узнать эпопею кодировки крякозябр можно тут.
ЛИНУКСФОРУМ ДЛЯ ЛЮДЕЙ | Гугляшечка | Блог
I'm banned by /dev/random with his team.
-
- Сообщения: 355
- ОС: Gentoo
-
- Сообщения: 355
- ОС: Gentoo
Re: Крякозябры ZIP
Кстати, я нашёл, как восстановить русский без LANG=C: 7z l 2xp.zip | iconv -t latin1 | iconv -f ibm866.
-
- Сообщения: 106
- ОС: Ubuntu
-
- Администратор
- Сообщения: 5403
- ОС: Gentoo
-
- Сообщения: 1
Перекодировал Крякозябры ZIP на питоне
Долго бился я с готовыми утилитами и в итоге решил вопрос питоном в два скрипта:
Сперва быстрый подбор, какая именно кодировка в архиве:
Теперь тупо распаковываем его (кодировка жёстко прописана в коде - поредактируйте это!
Надеюсь сэкономил кому-то час жизни
Shell
python ./zip_test_wrong_encodings.py ./archive.zip
python ./unzip_and_fix_filenames_encoding.py ./archive.zip
Сперва быстрый подбор, какая именно кодировка в архиве:
Код: Выделить всё
#zip_test_wrong_encodings.py
import zipfile
import sys
def test_zip_encodings(zip_path, sample_size=5):
print(f"Анализ архива: {zip_path}")
print("Пробуем разные кодировки...\n")
with zipfile.ZipFile(zip_path, 'r') as z:
filenames = z.namelist()[:sample_size] # Берём первые 5 файлов для примера
# Список возможных кодировок
encodings = [
'cp1251', # Windows-1251 (обычно для Windows)
'cp866', # DOS (альтернатива для старых архивов)
'koi8-r', # UNIX-кодировка (редко, но бывает)
'iso8859-5', # Кириллица (редко)
'utf-8', # На всякий случай
'cp437', # Старая DOS-кодировка (иногда используется в ZIP)
]
for enc in encodings:
print(f"=== Кодировка: {enc} ===")
try:
for name in filenames:
try:
# Пробуем декодировать имя
decoded_name = name.encode('cp437').decode(enc)
print(f" {decoded_name}")
except UnicodeError:
print(f" Ошибка декодирования: {name}")
except Exception as e:
print(f" Ошибка: {e}")
print() # Пустая строка для разделения
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Использование: python test_zip_encodings.py ARCHIVE.zip")
sys.exit(1)
test_zip_encodings(sys.argv[1])
Теперь тупо распаковываем его (кодировка жёстко прописана в коде - поредактируйте это!
Код: Выделить всё
#unzip_and_fix_filenames_encoding.py
import zipfile
import os
#[b] ИМЯ ФАЙЛА[/b] из командной строки (можно прописать в кавычках вместо [b]sys.argv[1][/b] - у меня не сработало в виндовском PowerShell)
zip_path = sys.argv[1]
output_dir = "output_folder"
os.makedirs(output_dir, exist_ok=True)
with zipfile.ZipFile(zip_path, 'r') as z:
for name in z.namelist():
# РЕДАКТИРУЕМ ТУТ (Декодируем в правильные русские буквы имя из CP866 в UTF-8)
correct_name = [b]name.encode('cp437').decode('cp866')[/b]
z.extract(name, output_dir)
# Переименовываем файл после извлечения
old_path = os.path.join(output_dir, name)
new_path = os.path.join(output_dir, correct_name)
os.rename(old_path, new_path)
print(f"Извлечено: {correct_name}")
print("готово.")
Надеюсь сэкономил кому-то час жизни