descomprimir ZIP con la codificación dada

26

Obtuve archivos ZIP, que contienen archivos, cuyos nombres están en alguna codificación. Digamos que sé la codificación de esos nombres de archivo, pero todavía no sé cómo descomprimirlos correctamente.

Aquí hay un archivo de ejemplo , contiene un archivo "【SSK 字幕 组】 The Vampire Diaries 吸血鬼 日记 S06E12.ass"

Sé que la codificación utilizada es GB18030 (chino)

La pregunta es: ¿cómo descomprimir ese archivo en FreeBSD usando descomprimir u otra utilidad CLI para obtener el nombre de archivo codificado adecuado? Intenté todo lo que pude, pero el resultado nunca fue bueno. Por favor ayuda.

Intenté en 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!

Intenté algo similar con descomprimir, pero me sale un problema similar.

Gracias, ahora estoy probando BSD GRATUITO, donde me estoy conectando usando SSH desde 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

Lo primero que me gustaría es mostrar correctamente los nombres chinos. Cambié

setenv LC_ALL zh_CN.GB18030
setenv LANG zh_CN.GB18030

Luego descargué el archivo e intenté "ls" para ver los caracteres correctos, pero no tuve suerte. Así que creo que tengo que resolver el primer idioma chino para verificar cuando obtengo el resultado adecuado, en realidad puedo compararlo. ¿Me pueden ayudar también con esto?

2ge
fuente

Respuestas:

22

Esto es lo que hago en Ubuntu 16.04 para descomprimir un zip en cualquier codificación, siempre que sepa cuál es esa codificación. El mismo método debería funcionar en FreeBSD porque solo se basa en una unzipherramienta ampliamente disponible .

  1. Verifico dos veces el nombre exacto de la codificación, para no escribir mal: https://www.iana.org/assignments/character-sets/character-sets.xhtml

  2. Simplemente corro

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

    o

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

    elegir entre -Oo -Isegún las instrucciones aquí:

    $ 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
      ...
    

    lo que significa que simplemente intento -O y debería funcionar, porque no mucha gente crearía un .ziparchivo en Unix ...


Entonces, para su ejemplo específico:

  1. El nombre de codificación exacto es GB18030.

  2. Yo uso la -O bandera y:

    $ 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.

mbdevpl
fuente
Para las cremalleras creadas por Windows griego, tuve éxito con este método y la codificación CP737
ndemou
¡Bravo! Verifiqué dos veces la página de manual, en realidad funciona pero está totalmente indocumentada, ninguna de las terminaciones de zsh tiene este parámetro.
ttimasdf
2
unzipno tiene esta opción en Mac OS X y siempre crea nombres de archivo con codificación porcentual. La unarsugerencia de @javacom funcionó de maravilla .
Phil Krylov
Parece una funcionalidad específica de Debian. Mi unzipdice que es UnZip 6.00 of 20 April 2009, by Info-ZIP. Maintained by C. Spielery no proporciona tales opciones.
L29Ah
2
@ L29Ah My unzipen Debian 9 es exactamente la misma versión y no tiene tales opciones. ¿Probablemente Ubuntu específico?
Arnie97
11

En la mayoría de los sistemas de archivos POSIX, el nombre de archivo es solo una serie de bytes y depende del espacio del usuario darle sentido. Puedes usar esto a tu favor.

  1. Primero, extraiga el archivo usando bsdtar, ya que la unzipherramienta parece alterar los nombres de los archivos, mientras que bsdtar los extraerá sin procesar. (Estoy probando esto en Linux. Supongo que FreeBSD simplemente lo llama tar).

    $ bsdtar xf gb18030.zip
    
  2. Verifique que herramientas como iconvpueden decodificar con éxito los nombres:

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

    (Tenga en cuenta que esto solo afecta a la findsalida, no a los archivos).

  3. Finalmente, use convmvpara convertir los nombres de archivo a UTF-8:

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

    (Nota: tuve que instalar Encode :: HanExtra de CPAN para el soporte GB18030 y agregarlo manualmente use Encode::HanExtra;a / usr / bin / convmv aunque se supone que debe

  4. En caso de convmvque no esté disponible, escríbalo:

    $ 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
    

    (Al menos en Linux, tiene la ventaja de que iconvcasi siempre está disponible y siempre es compatible con gb18030).

usuario1686
fuente
gracias Grawity investigando esto. Estoy probando ahora mismo en OSX (pero eso está muy cerca de FreeBSD, y creo que el resultado será similar). agregar comentario a mi pregunta, no se puede editar aquí ...
2ge
1
@ 2ge: Ah, OSX podría ser bastante diferente, ya que HFS + fuerza internamente los nombres de archivo en NFD UTF-16 en lugar de almacenar cadenas de bytes, por lo que existe la posibilidad de que corrompa los nombres GB18030 antes de que tenga la oportunidad de convertirlos.
user1686
Edité la pregunta original, agregué algunos comentarios más.
2ge
Sí, lo probé en macOS Sierra y bsdtar informó muchos errores "Error al crear xxx" (porque los nombres del directorio principal son corrput). Tuve que copiar mi archivo a un VPS de Linux, usar descomprimir -O para extraerlo y copiar el resultado a mi Mac usando ssh -C.
Chang Qian
10

Método 1 : use la utilidad unar

sudo apt-get install unar

unar -e gb18030 gb18030.zip

Método 2 : utilice un script de Python para descomprimir el archivo (consulte 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()

El ejemplo gb18030.zip extraerá el siguiente archivo

【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12
【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12/【SSK字幕组】The Vampire Diaries 吸血鬼日记S06E12.ass
javacom
fuente
2
Gracias, el unarmétodo es el más sencillo al menos en Mac OS X.
Phil Krylov
4

En OS X, puede usar una aplicación GUI llamada The Unarchiver . Se puede instalar usando Mac App Store o Homebrew Cask :

brew cask install the-unarchiver

Cuando abre un archivo ZIP con él, la aplicación le permite elegir la codificación adecuada mediante la vista previa de un nombre de archivo del archivo.

Melebio
fuente
4

7z admite ID de juego de caracteres con un interruptor -scs, por ejemplo:

7z x -scs903 some.zip

donde 903 es 中文 簡體 charset. Puede encontrar una lista más larga de ID de juego de caracteres aquí .

Oh ho
fuente
2
7z -scsEl interruptor elige solo la codificación de la @lista de archivos definidos.
Phil Krylov
1

Usa 7z para extraer el archivo

7z x yourfile.zip

Después de eso, convierta la codificación de esos nombres de archivo usted mismo:

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

Esto funciona para mí ... from_encoding en mi caso es tis-620 (que es una codificación tailandesa), necesita encontrar una codificación adecuada de su idioma. Una popular generalmente resuelve el problema, pero si el nombre del archivo aún no se puede leer, intente cambiar de_coding a otras cosas como windows-1252 o shift-jis (japonés) o lo que sea, puede enumerar la codificación disponible usando el comando:

convmv --list
iconv --list

Este es un método muy simple de "cómo resolverlo" para mí.

off99555
fuente
0

Acabo de usar 7zip y logró elegir la codificación correcta.

(algo que el zip estándar no podía hacer)

pero lo usé en Windows, con la herramienta GUI. Tal vez la línea de comando 7z también funcione para usted.

Berry Tsakala
fuente
Hay una respuesta que recomienda 7z y su respuesta no agrega nada más.
Melebius
1
Sí, ahora hay otra respuesta que recomienda 7z. Difícilmente puede esperar que la respuesta de Berry "agregue más" a una respuesta que se publicó casi cinco meses después.
Scott
@Scott Mis disculpas, no pude leer las abreviaturas de los meses en inglés correctamente.
Melebius
OKAY. Es posible que desee saber que, si coloca el puntero del mouse sobre cualquier fecha en la página (y "pasa el cursor" allí), le mostrará la fecha como números. (Al menos esto funciona en las computadoras; la gente dice que no funciona bien en los teléfonos). Además, debajo de la esquina inferior derecha de la pregunta, verá "votos más antiguos activos". Este es el orden de respuesta. Si hace clic en "más antiguo", obtendrá las respuestas en orden de más antiguo a más nuevo.
Scott