Aquí podría ser tu PUBLICIDAD


Descomprimir la estructura del directorio con python

votos
28

Tengo un archivo zip que contiene la siguiente estructura de directorio:

dir1\dir2\dir3a
dir1\dir2\dir3b

Estoy tratando de descomprimirlo y mantener la estructura de directorios, sin embargo, recibo el error:

IOError: [Errno 2] No such file or directory: 'C:\\\projects\\\testFolder\\\subdir\\\unzip.exe'

donde testFolder es dir1 arriba y subdir es dir2.

¿Hay alguna forma rápida de descomprimir el archivo y mantener la estructura del directorio?

Publicado el 12/03/2009 a las 19:44
fuente por usuario Flyer1
En otros idiomas...        العربية       

9 respuestas

votos
22

Los métodos extract y extractall son geniales si estás en Python 2.6. Tengo que usar Python 2.5 por ahora, así que solo necesito crear los directorios si no existen. Puede obtener una lista de directorios con el namelist()método. Los directorios siempre terminarán con una barra inclinada (incluso en Windows), por ejemplo,

import os, zipfile

z = zipfile.ZipFile('myfile.zip')
for f in z.namelist():
    if f.endswith('/'):
        os.makedirs(f)

Probablemente no quieras hacerlo exactamente así (es decir, probablemente quieras extraer el contenido del archivo zip mientras iteras sobre la lista de nombres), pero te da la idea.

Respondida el 12/03/2009 a las 08:11
fuente por usuario Jeff


Aquí podría ser tu PUBLICIDAD


votos
15

No confíes en extract () o extractall ().

Estos métodos extraen ciegamente archivos a las rutas dadas en sus nombres de archivo. Pero los nombres de archivo ZIP pueden ser cualquier cosa, incluidas cadenas peligrosas como "x /../../../ etc / passwd". Extraiga esos archivos y podría haber comprometido todo su servidor.

Tal vez esto debería considerarse un agujero de seguridad reportable en el módulo zipfile de Python, pero cualquier número de zip-dearchivers han exhibido exactamente el mismo comportamiento en el pasado. Para desarchivar un archivo ZIP con estructura de carpetas de forma segura, necesita una verificación en profundidad de cada ruta de archivo.

Respondida el 13/03/2009 a las 01:56
fuente por usuario bobince

votos
7

Probé esto y puedo reproducirlo. El método extractall, como lo sugieren otras respuestas, no resuelve el problema. Esto parece un error en el módulo de archivo zip para mí (¿solo para Windows?), A menos que no entienda cómo se estructuran los archivos zip.

testa\
testa\testb\
testa\testb\test.log
> test.zip

>>> from zipfile import ZipFile
>>> zipTest = ZipFile("C:\\...\\test.zip")
>>> zipTest.extractall("C:\\...\\")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\zipfile.py", line 940, in extractall
  File "...\zipfile.py", line 928, in extract
  File "...\zipfile.py", line 965, in _extract_member
IOError: [Errno 2] No such file or directory: 'C:\\...\\testa\\testb\\test.log'

Si hago una printdir(), obtengo esto (primera columna):

>>> zipTest.printdir()
File Name
testa/testb/
testa/testb/test.log

Si trato de extraer solo la primera entrada, así:

>>> zipTest.extract("testa/testb/")
'C:\\...\\testa\\testb'

En el disco, esto da como resultado la creación de una carpeta testa, con un archivo testb dentro. Esta es aparentemente la razón por la cual el intento subsiguiente de extraer test.logfalla; testa\testbes un archivo, no una carpeta.

Editar # 1: si extrae solo el archivo, entonces funciona:

>>> zipTest.extract("testa/testb/test.log")
'C:\\...\\testa\\testb\\test.log'

Editar # 2: el código de Jeff es el camino a seguir; iterar a través de namelist; si es un directorio, crea el directorio. De lo contrario, extrae el archivo.

Respondida el 12/03/2009 a las 08:11
fuente por usuario DNS

votos
6

Sé que puede ser un poco tarde para decir esto, pero Jeff es correcto. Es tan simple como:

import os
from zipfile import ZipFile as zip

def extractAll(zipName):
    z = zip(zipName)
    for f in z.namelist():
        if f.endswith('/'):
            os.makedirs(f)
        else:
            z.extract(f)

if __name__ == '__main__':
    zipList = ['one.zip', 'two.zip', 'three.zip']
    for zip in zipList:
        extractAll(zipName)
Respondida el 25/06/2011 a las 03:32
fuente por usuario ki113d

votos
3

Hay una manera muy fácil si estás usando Python 2.6: el método extractall .

Sin embargo, dado que el zipfilemódulo se implementa completamente en Python sin extensiones C, probablemente pueda copiarlo de una instalación 2.6 y usarlo con una versión anterior de Python; puede encontrar esto más fácil que tener que volver a implementar la funcionalidad usted mismo. Sin embargo, la función en sí es bastante corta:

def extractall(self, path=None, members=None, pwd=None):
    """Extract all members from the archive to the current working
       directory. `path' specifies a different directory to extract to.
       `members' is optional and must be a subset of the list returned
       by namelist().
    """
    if members is None:
        members = self.namelist()

    for zipinfo in members:
        self.extract(zipinfo, path, pwd)
Respondida el 12/03/2009 a las 08:03
fuente por usuario Eli Courtwright

votos
2

Si como yo, tiene que extraer un archivo zip completa con una versión anterior de Python (en mi caso, 2.4) esto es lo que ocurrió con (basado en la respuesta de Jeff):

import zipfile
import os

def unzip(source_file_path, destination_dir):
    destination_dir += '/'
    z = zipfile.ZipFile(source_file_path, 'r')
    for file in z.namelist():
        outfile_path = destination_dir + file
        if file.endswith('/'):
            os.makedirs(outfile_path)
        else:
            outfile = open(outfile_path, 'wb')
            outfile.write(z.read(file))
            outfile.close()
    z.close()
Respondida el 18/03/2015 a las 10:13
fuente por usuario Apteryx

votos
2

Filtrar la lista de nombres para excluir las carpetas

Todo lo que tiene que hacer es filtrar las namelist()entradas que terminan en /y el problema se resuelve:

  z.extractall(dest, filter(lambda f: not f.endswith('/'), z.namelist()))

nJoy!

Respondida el 26/08/2012 a las 01:20
fuente por usuario nickl-

votos
2

Parece que estás intentando ejecutar descomprimir para extraer el zip.

Sería mejor usar el zipfilemódulo python , y por lo tanto hacer la extracción en python.

import zipfile

def extract(zipfilepath, extractiondir):
    zip = zipfile.ZipFile(zipfilepath)
    zip.extractall(path=extractiondir)
Respondida el 12/03/2009 a las 08:03
fuente por usuario Douglas Leeder

votos
1

Tenga en cuenta que los archivos zip puede tener entradas para directorios, así como archivos. Al crear archivos con el zipcomando, pasando la -Dopción de desactivar la inclusión de entradas de directorio de forma explícita en el archivo. Cuando Python 2.6 ZipFile.extractallmétodo se ejecuta a través de una entrada de directorio, parece crear un archivo en su lugar. Desde entradas del archivo no están necesariamente en orden, esto causa ZipFile.extractalla fallar con bastante frecuencia, ya que trata de crear un archivo en un subdirectorio de un archivo. Si usted tiene un archivo que desea utilizar con el módulo de Python, basta con extraer y re-ZIP con la -Dopción. He aquí un pequeño fragmento He estado usando durante un tiempo para hacer exactamente eso:

P=`pwd` && 
Z=`mktemp -d -t zip` && 
pushd $Z && 
unzip $P/<busted>.zip && 
zip -r -D $P/<new>.zip . && 
popd && 
rm -rf $Z

Vuelva a colocar <busted>.zipy <new>.zipcon nombres reales en relación con el directorio actual. A continuación, sólo copiar todo el asunto y pégala en una consola de comandos, y se creará un nuevo archivo con el que está listo para oscilar con Python 2.6. No es un zipcomando que eliminar estas entradas de directorio sin descomprimir pero IIRC se comportó extrañamente diferente en el intérprete de comandos o configuraciones zip.

Respondida el 27/02/2010 a las 03:27
fuente por usuario xdissent