распаковать ZIP с заданной кодировкой

26

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

Вот пример файла , он содержит один файл "【SSK 字幕 组】 Дневники вампира 吸血鬼 日记 S06E12.ass"

Я знаю, что используется кодировка GB18030 (китайский)

Вопрос - как распаковать этот файл во FreeBSD с помощью unzip или другой утилиты CLI, чтобы получить правильное закодированное имя файла? Я перепробовал все, что мог, но результат никогда не был хорошим. Пожалуйста помоги.

Я попробовал на OSX:

MBP1:test 2ge$ bsdtar xf gb18030.zip
MBP1:test 2ge$ ls
%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12/      gb18030.zip
MBP1:test 2ge$ cd %A1%BESSK%D7%D6Ļ%D7顿The\ Vampire\ Diaries\ %CE%FCѪ%B9%ED%C8ռ%C7S06E12/
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ ls
%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12.ass*
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ find . | iconv -f gb18030 -t utf-8
.
./%A1%BESSK%D7%D6L抬%D7椤縏he Vampire Diaries %CE%FC血%B9%ED%C8占%C7S06E12.ass 
MBP1:%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12 2ge$ convmv -r -f gb18030 -t utf-8 --notest .
Skipping, already UTF-8: ./%A1%BESSK%D7%D6Ļ%D7顿The Vampire Diaries %CE%FCѪ%B9%ED%C8ռ%C7S06E12.ass
Ready!

Я пробовал подобное с unzip, но я получаю похожую проблему.

Спасибо, теперь примеряю БЕСПЛАТНО BSD, где я подключаюсь по SSH из OSX (Терминал):

# locale
LANG=
LC_CTYPE="C"
LC_COLLATE="C"
LC_TIME="C"
LC_NUMERIC="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_ALL=C

Во-первых, я бы хотел правильно показать китайские имена. я изменил

setenv LC_ALL zh_CN.GB18030
setenv LANG zh_CN.GB18030

Затем я скачал файл и попытался "ls", чтобы увидеть правильные символы, но не удачу. Поэтому я думаю, что мне нужно решить первую китайскую локаль, чтобы проверить, когда я получу правильный результат, на самом деле я могу сравнить его. Можете ли вы помочь мне, пожалуйста, с этим?

2Ge
источник

Ответы:

22

Вот что я делаю в Ubuntu 16.04, чтобы распаковать zip в любую кодировку, если я знаю, что это за кодировка. Тот же метод должен работать на FreeBSD, потому что он опирается только на широко доступный unzipинструмент.

  1. Я дважды проверил точное название кодировки, чтобы не ошибиться: https://www.iana.org/assignments/character-sets/character-sets.xhtml

  2. Я просто бегаю

    $ unzip -O <encoding> <filename> -d <target_dir>
    

    или

    $ unzip -I <encoding> <filename> -d <target_dir>
    

    выбирая между -Oили в -Iсоответствии с инструкциями здесь:

    $ unzip -h
    UnZip 6.00 of 20 April 2009, by Debian. Original by Info-ZIP.
      ...
      -O CHARSET  specify a character encoding for DOS, Windows and OS/2 archives
      -I CHARSET  specify a character encoding for UNIX and other archives
      ...
    

    что означает, что я просто пытаюсь, -Oи это должно работать, потому что не многие люди создают .zipфайл в Unix ...


Итак, для вашего конкретного примера:

  1. Точное название кодировки GB18030.

  2. Я использую -Oфлаг и:

    $ unzip -O GB18030 gb18030.zip -d target_dir
    Archive:  gb18030.zip
       creating: target_dir/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/
      inflating: target_dir/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass
    

    ... оно работает.

mbdevpl
источник
Для почтовых
индексов,
Браво! Я дважды проверил страницу руководства, она на самом деле работает, но полностью недокументирована, ни у одного zsh-завершения нет этого параметра.
ttimasdf
3
unzipне имеет этой опции в Mac OS X и всегда создает закодированные в процентах имена файлов. Предложение @ javacom unarсработало как шарм.
Фил Крылов
Похоже на функциональность, специфичную для Debian. Мой unzipговорит, что UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spielerи не предоставляет такие варианты.
L29Ah
2
@ L29Ah У меня unzipв Debian 9 точно такая же версия и нет таких опций. Наверное, специфичный для Ubuntu?
Arnie97
11

В большинстве файловых систем POSIX имя файла представляет собой просто серию байтов, и пользовательское пространство может его понять. Вы можете использовать это в ваших интересах.

  1. Во-первых, распакуйте архив, используя bsdtar, так как unzipинструмент, кажется, манипулирует именами файлов, а bsdtar извлечет их в сыром виде. (Я тестирую это на Linux. Я думаю, что FreeBSD просто вызывает это tar.)

    $ bsdtar xf gb18030.zip
    
  2. Убедитесь, что такие инструменты, как iconvможно успешно декодировать имена:

    $ find . | iconv -f gb18030 -t utf-8
    

    (Обратите внимание, что это влияет только на findвывод, а не на сами файлы.)

  3. Наконец, используйте convmvдля преобразования имен файлов в UTF-8:

    $ convmv -r -f gb18030 -t utf-8 --notest .
    

    (Примечание: мне пришлось установить Encode :: HanExtra из CPAN для поддержки GB18030 и вручную добавить use Encode::HanExtra;в / usr / bin / convmv, даже если он должен

  4. В случае, если convmvон недоступен, запишите его:

    $ find . -depth | while read -r old; do
        old=./$old;
        head=${old%/*};
        tail=${old##*/};
        new=$head/$(echo "$tail" | iconv -f gb18030 -t utf-8);
        [ "$old" = "$new" ] || mv "$old" "$new";
    done
    

    (По крайней мере, в Linux это имеет преимущество в том, что iconvоно почти всегда доступно и всегда поддерживает gb18030.)

user1686
источник
спасибо, благодарность, глядя на это. Я сейчас тестирую на OSX (но это очень близко к FreeBSD, и я думаю, что результат будет похожим). добавив комментарий к моему вопросу, не можете редактировать здесь ...
2ge
1
@ 2ge: Да, OSX на самом деле может сильно отличаться, поскольку HFS + внутренне вводит имена файлов в NFD UTF-16, а не хранит строки байтов, поэтому есть вероятность, что они повредят имена GB18030, прежде чем вы получите возможность конвертировать их.
user1686
Я отредактировал оригинальный вопрос, добавив еще несколько комментариев.
2Ge
Да, я попробовал это на macOS Sierra, и bsdtar сообщала о множестве ошибок «Не удалось создать xxx» (поскольку имена родительских каталогов являются corrput). Пришлось скопировать мой архив на VPS Linux, использовать unzip -O, чтобы распаковать его, и скопировать результат обратно на мой Mac, используя ssh -C.
Чан Цянь
10

Способ 1 : используйте утилиту unar

sudo apt-get install unar

unar -e gb18030 gb18030.zip

Способ 2. Использование сценария Python для распаковки файла (ссылка https://gist.github.com/usunyu/dfc6e56af6e6caab8018bef4c3f3d452#file-gbk-unzip-py )

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# unzip-gbk.py

import os
import sys
import zipfile
import argparse

parser = argparse.ArgumentParser()
parser.add_argument("--encoding", help="encoding for filename, default gbk")
parser.add_argument("-l", help="list filenames in zipfile, do not unzip", action="store_true")
parser.add_argument("file", help="process file.zip")
args = parser.parse_args()
print "Processing File " + args.file

file=zipfile.ZipFile(args.file,"r");
if args.encoding:
    print "Encoding " + args.encoding
for name in file.namelist():
    if args.encoding:
        utf8name=name.decode(args.encoding)
    else:
        utf8name=name.decode('gbk')
    pathname = os.path.dirname(utf8name)
    if args.l:
        print "Filename " + utf8name
    else:
        print "Extracting " + utf8name
        if not os.path.exists(pathname) and pathname!= "":
            os.makedirs(pathname)
        data = file.read(name)
        if not os.path.exists(utf8name):
            fo = open(utf8name, "w")
            fo.write(data)
            fo.close
file.close()

Пример gb18030.zip извлечет следующий файл

【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12
【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass
javacom
источник
2
Спасибо, этот unarметод наиболее беспроблемен, по крайней мере, в Mac OS X.
Фил Крылов
4

На OS X вы можете использовать приложение с графическим интерфейсом под названием Unarchiver . Его можно установить с помощью Mac App Store или Homebrew Cask :

brew cask install the-unarchiver

Когда вы открываете ZIP-файл с ним, приложение позволяет вам выбрать подходящую кодировку, используя предварительный просмотр имени файла из архива.

Melebius
источник
4

7z поддерживает идентификатор кодировки с помощью переключателя -scs, например:

7z x -scs903 some.zip

где 903 - это кодировка Более длинный список идентификаторов кодировки можно найти здесь .

ohho
источник
2
7z -scsПараметр switch выбирает только кодировку @списка определенных файлов.
Фил Крылов
1

Используйте 7z, чтобы извлечь файл

7z x yourfile.zip

После этого преобразуйте кодировку этих имен самостоятельно:

convmv --notest -f from_encoding -t utf-8 -r your_extracted_folder/

Это работает для меня .. В моем случае из_encoding является tis-620 (это тайская кодировка), вам нужно найти подходящую кодировку вашего языка. Популярный обычно решает проблему, но если имя файла по-прежнему нечитаемо, попробуйте изменить от -encoding к другим вещам, таким как windows-1252 или shift-jis (японский) или что-то еще, вы можете перечислить доступную кодировку, используя команду:

convmv --list
iconv --list

Это очень простой метод «как решить» для меня.

off99555
источник
0

Я просто использовал 7zip, и ему удалось выбрать правильную кодировку.

(то, что не мог сделать стандартный почтовый индекс)

но использовал его на Windows, с инструментом GUI. Возможно, командная строка 7z тоже подойдет вам.

Ягода Цакала
источник
Существует ответ, рекомендующий 7z, и ваш ответ больше ничего не добавляет к нему.
Мелебиус
1
Да, теперь есть другой ответ, рекомендующий 7z. Вы вряд ли можете ожидать, что ответ Берри «добавит больше» к ответу, опубликованному почти пять месяцев спустя.
Скотт
@ Scott Мои извинения, я не смог правильно прочитать английские сокращения месяца.
Мелебиус
OK. Возможно, вы захотите знать, что, если вы наведете указатель мыши на любую дату на странице (и наведите указатель мыши на нее), она покажет вам дату в виде чисел. (По крайней мере, это работает на компьютерах; люди говорят, что это не работает на телефонах.) Кроме того, ниже правого нижнего угла вопроса вы увидите «активные самые старые голоса». Это порядок сортировки ответов. Если вы нажмете «самый старый», то вы получите ответы в порядке от самого старого до самого нового.
Скотт