descompacte ZIP com a codificação fornecida


25

Eu tenho arquivos ZIP, que contêm arquivos, cujos nomes de arquivos estão em alguma codificação. Digamos que eu conheça a codificação desses nomes de arquivos, mas ainda não sei como descompactá-los adequadamente.

Aqui está um arquivo de exemplo , ele contém um arquivo "【SSK iaries 组】 The Vampire Diaries 日记 日记 S06E12.ass"

Eu sei que a codificação usada é GB18030 (chinês)

A questão é - como descompactar esse arquivo no FreeBSD usando o descompactação ou outro utilitário CLI para obter o nome do arquivo codificado adequado? Eu tentei de tudo o que pude, mas o resultado nunca foi bom. Por favor ajude.

Eu tentei no 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!

Tentei semelhante com descompactar, mas tenho um problema semelhante.

Obrigado, agora experimentando FREE BSD, onde estou conectando usando SSH do OSX (Terminal):

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

A primeira coisa que eu gostaria é mostrar corretamente os nomes chineses. eu mudei

setenv LC_ALL zh_CN.GB18030
setenv LANG zh_CN.GB18030

Então baixei o arquivo e tentei "ls" para ver os caracteres adequados, mas não a sorte. Então, eu acho que tenho que resolver o primeiro código do idioma chinês para verificar quando eu obtenho o resultado adequado, na verdade eu posso compará-lo. Você também pode me ajudar por favor com isso?

Respostas:


22

Aqui está o que eu faço no Ubuntu 16.04 para descompactar um zip em qualquer codificação, desde que eu saiba o que é essa codificação. O mesmo método deve funcionar no FreeBSD, porque ele depende apenas de uma unzipferramenta amplamente disponível .

  1. Verifico duas vezes o nome exato da codificação, para não escrever errado: https://www.iana.org/assignments/character-sets/character-sets.xhtml

  2. Eu simplesmente corro

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

    ou

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

    escolhendo entre -Oou de -Iacordo com as instruções aqui:

    $ 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 que significa que eu simplesmente tento -Oe deve funcionar, porque muitas pessoas não criariam um .ziparquivo no Unix ...


Então, para o seu exemplo específico:

  1. O nome exato da codificação é GB18030.

  2. Eu uso a -Obandeira e:

    $ 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
    

    ... funciona.


Para zips criados por grega do Windows eu tive sucesso com este método e codificação CP737
ndemou

Bravo! Eu verifiquei novamente a página do manual, ela realmente funciona, mas totalmente indocumentada, nenhuma a conclusão do zsh tem esse parâmetro.
Ttimasdf 29/03/19

2
unzipnão possui essa opção no Mac OS X e sempre cria nomes de arquivos com porcentagem codificada. A unarsugestão de @ javacom funcionou como um encanto.
22419 Phil Krylov

Parece uma funcionalidade específica do Debian. Meu unzipdiz que é UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spielere não fornece essas opções.
L29Ah

11
@ L29Ah O My unzipno Debian 9 é exatamente a mesma versão e não possui essas opções. Provavelmente específico do Ubuntu?
Arnie97

11

Na maioria dos sistemas de arquivos POSIX, o nome do arquivo é apenas uma série de bytes e cabe ao espaço do usuário fazer algum sentido. Você pode utilizar isto para o seu benefício.

  1. Primeiro, extraia o arquivo usando bsdtar, pois a unzipferramenta parece alterar os nomes dos arquivos, enquanto o bsdtar os extrairá em bruto. (Estou testando isso no Linux. Acho que o FreeBSD apenas chama tar.)

    $ bsdtar xf gb18030.zip
    
  2. Verifique se ferramentas como iconvpodem decodificar com êxito os nomes:

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

    (Observe que isso afeta apenas a findsaída, não os próprios arquivos.)

  3. Por fim, use convmvpara converter os nomes de arquivo em UTF-8:

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

    (Nota: eu tive que instalar o Encode :: HanExtra do CPAN para o suporte GB18030 e adicionar manualmente use Encode::HanExtra;a / usr / bin / convmv, mesmo que seja necessário

  4. Caso convmvnão esteja disponível, escreva-o:

    $ 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
    

    (Pelo menos no Linux, isso tem uma vantagem em iconvestar quase sempre disponível e sempre suportar gb18030.)


graças grawity olhando para isso. Estou testando agora no OSX (mas isso é muito parecido com o FreeBSD, e acho que o resultado será semelhante). adicionando comentário à minha pergunta, não é possível editar aqui ... #
2ge 02/02

11
@ 2ge: Ah, o OSX pode ser bem diferente, pois o HFS + força internamente os nomes de arquivos no NFD UTF-16, em vez de armazenar as seqüências de bytes, então existe a possibilidade de que ele corrompa os nomes do GB18030 antes que você possa convertê-los.
user1686

Eu editei a pergunta original, adicione mais alguns comentários.
2GE

Sim, eu tentei no macOS Sierra e o bsdtar relatou muitos erros "Falha ao criar xxx" (porque os nomes dos diretórios principais são de corrupção). Tive que copiar meu arquivo em um VPS do Linux, use descompacte -O para extraí-lo e copie o resultado de volta para o meu Mac usando ssh -C.
Chang Qian

10

Método 1 : usar o utilitário unar

sudo apt-get install unar

unar -e gb18030 gb18030.zip

Método 2 : Use um script python para descompactar o arquivo (referência 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()

O exemplo gb18030.zip extrairá o seguinte arquivo

【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12
【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass

2
Obrigado, o unarmétodo é o mais livre de problemas, pelo menos no Mac OS X.
Phil Krylov

4

No OS X, você pode usar um aplicativo GUI chamado The Unarchiver . Pode ser instalado usando a Mac App Store ou o Homebrew Cask :

brew cask install the-unarchiver

Quando você abre um arquivo ZIP com ele, o aplicativo permite escolher a codificação apropriada usando a visualização de um nome de arquivo do arquivo morto.


4

7z suporta ID de conjunto de caracteres com um comutador -scs, por exemplo:

7z x -scs903 some.zip

onde 903 é 簡體 簡體 charset. Uma lista mais longa de IDs de conjunto de caracteres pode ser encontrada aqui .


2
7z -scsO switch escolhe apenas a codificação da @lista de arquivos definidos.
22418 Phil Krylov #

1

Use 7z para extrair o arquivo

7z x yourfile.zip

Depois disso, converta você mesmo a codificação desses nomes de arquivos:

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

Isso funciona para mim .. from_encoding no meu caso é tis-620 (que é uma codificação tailandesa), você precisa encontrar uma codificação apropriada do seu idioma. Um popular geralmente resolve o problema, mas se o nome do arquivo ainda estiver ilegível, tente alterar de_encoding para outras coisas, como windows-1252 ou shift-jis (japonês) ou qualquer outra coisa, você pode listar a codificação disponível usando o comando:

convmv --list
iconv --list

Este é um método muito simples de "como resolver" para mim.


-1

Acabei de usar o 7zip e ele conseguiu escolher a codificação correta.

(algo que o zip padrão não poderia fazer)

mas o usou no Windows, com a ferramenta GUI. Talvez a linha de comando 7z funcione para você também.


Há uma resposta recomendando 7z e sua resposta não acrescenta mais nada.
Melebius

11
Sim, agora há outra resposta recomendando 7z. Você mal pode esperar que a resposta de Berry “adicione mais” a uma resposta publicada quase cinco meses depois.
Scott

@ Scott As minhas desculpas, não consegui ler as abreviações do mês em inglês corretamente.
Melebius

ESTÁ BEM. Você pode querer saber que, se colocar o ponteiro do mouse sobre qualquer data da página (e “passar o mouse”), ela mostrará a data como números. (Pelo menos isso funciona em computadores; as pessoas dizem que não funciona bem em telefones.) Além disso, abaixo do canto inferior direito da pergunta, você verá "votos mais antigos ativos". Essa é a ordem de resposta. Se você clicar em "mais antigo", obterá as respostas na ordem do mais antigo para o mais novo.
Scott
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.