Extrahieren von Dateien mit ungültigen Zeichen in Dateinamen mit Python
Frage
Ich benutze python zipfile-Modul zu extrahieren .zip-Archiv (nehmen wir mal diese Datei bei http://img.dafont.com/dl/?f=akvaleir zum Beispiel.)
f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
print fileinfo.filename
f.extract(fileinfo, '.')
Seine Ausgabe:
Akval�ir_Normal_v2007.ttf
Akval�ir, La police - The Font - Fr - En.pdf
Beide Dateien sind unaccessable nach der Extraktion, weil es ungültige codierte Zeichen in Ihren Dateinamen.Das problem ist zipfile-Modul verfügt nicht über eine option aus, um anzugeben Ausgabe-Dateinamen.
Allerdings "entpacken akvaleir.zip" entgeht dem Dateinamen auch:
root@host:~# unzip akvaleir.zip
Archive: akvaleir.zip
inflating: AkvalВir_Normal_v2007.ttf
inflating: AkvalВir, La police - The Font - Fr - En.pdf
Ich habe versucht, die Erfassung Ausgabe von "unzip-l akvaleir.zip" in meinem python-Programm, und diese beiden Dateinamen sind:
Akval\xd0\x92ir_Normal_v2007.ttf
Akval\xd0\x92ir, La police - The Font - Fr - En.pdf
Wie bekomme ich den korrekten Dateinamen wie das, was unzip-Befehl wird ohne die Erfassung Ausgabe von "unzip-l akvaleir.zip"?
Lösung
Anstelle der extract
Methode, verwenden Sie die open
Methode und speichern Sie die resultierende pseudofile auf der Festplatte, unter welchem Namen auch immer Sie wünschen, zum Beispiel mit shutil.copyfileobj
.
Andere Tipps
Es dauerte einige Zeit, aber ich denke, dass ich die Antwort gefunden.
nahm ich das Wort sollte Akvaléir sein. Ich fand eine Seite Beschreibung darüber, auf Französisch. Wenn ich Ihr Code-Snippet verwendet wurde, hatte ich eine Zeichenfolge wie
>>> fileinfo.filename
'Akval\x82ir, La police - The Font - Fr - En.pdf'
>>>
Das ist nicht in UTF8 funktionierte, Latin-1, CP-1251 oder CP-1252-Codierungen. Ich fand dann, dass CP863 war eine mögliche kanadische Codierung, so vielleicht ist dies von Französisch-Kanada war.
>>> print unicode(fileinfo.filename, "cp863").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>>
Allerdings habe ich dann lesen Sie die Zip-Spezifikation Dateiformat, das sagt
Das ZIP-Format hat historisch unterstützt nur die ursprüngliche IBM PC Zeichencodierungssatz, häufig bezeichnet als IBM-Codepage 437.
...
Wenn Allzweck Bit 11 gesetzt ist, die Dateiname und Kommentar muss unterstützt die Unicode Standard, Version 4.1.0 oder größer unter Verwendung der Zeichencodierung von dem UTF-8-Speicher definierten Form Spezifikation.
des Testen heraus gibt mir die gleiche Antwort wie die kanadische Codepage
>>> print unicode(fileinfo.filename, "cp437").encode("utf8")
Akvaléir, La police - The Font - Fr - En.pdf
>>>
Ich habe eine Unicode nicht Zip-Datei verschlüsselt und ich werde nicht erstellen, um herauszufinden, also werde ich einfach davon ausgehen, dass alle Zip-Dateien, die CP437-Codierung haben.
import shutil
import zipfile
f = zipfile.ZipFile('akvaleir.zip', 'r')
for fileinfo in f.infolist():
filename = unicode(fileinfo.filename, "cp437")
outputfile = open(filename, "wb")
shutil.copyfileobj(f.open(fileinfo.filename), outputfile)
Auf meinem Mac, das gibt
109936 Nov 27 01:46 Akvale??ir_Normal_v2007.ttf
25244 Nov 27 01:46 Akvale??ir, La police - The Font - Fr - En.pdf
, welches Register vervollständigt zu
ls Akvale\314\201ir
und zeigt mit einem schön 'é' in meinem Datei-Browser.
Ich lief in ein ähnliches Problem, während meine Anwendung ausgeführt Docker verwenden. Addiert man diese Zeilen in die Dockerfile, fest alles für mich:
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
Also, ich denke, wenn Sie nicht Docker verwenden, probieren Sie es aus und stellen Sie sicher, locales richtig erzeugt werden und eingestellt werden.