comprimir archivos python file zip folder zipfile

comprimir archivos python



Agregar carpetas a un archivo zip usando python (12)

Quiero crear un archivo zip. Agregue una carpeta al archivo zip y luego agregue un grupo de archivos a esa carpeta.

Así que quiero terminar con un archivo zip con una sola carpeta con archivos.

No sé si es una mala práctica tener carpetas en archivos zip o algo así, pero Google no me da nada sobre el tema.

Empecé con esto:

def addFolderToZip(myZipFile,folder): folder = folder.encode(''ascii'') #convert path to ascii for ZipFile Method for file in glob.glob(folder+"/*"): if os.path.isfile(file): print file myZipFile.write(file, os.path.basename(file), zipfile.ZIP_DEFLATED) elif os.path.isdir(file): addFolderToZip(myZipFile,file) def createZipFile(filename,files,folders): curTime=strftime("__%Y_%m_%d", time.localtime()) filename=filename+curTime; print filename zipFilename=utils.getFileName("files", filename+".zip") myZipFile = zipfile.ZipFile( zipFilename, "w" ) # Open the zip file for writing for file in files: file = file.encode(''ascii'') #convert path to ascii for ZipFile Method if os.path.isfile(file): (filepath, filename) = os.path.split(file) myZipFile.write( file, filename, zipfile.ZIP_DEFLATED ) for folder in folders: addFolderToZip(myZipFile,folder) myZipFile.close() return (1,zipFilename) (success,filename)=createZipFile(planName,files,folders);

Tomado de: http://mail.python.org/pipermail/python-list/2006-August/396166.html

Que se deshace de todas las carpetas y coloca todos los archivos en la carpeta de destino (y sus subcarpetas) en un solo archivo zip. No pude conseguir que agregue una carpeta completa.

Si paso la ruta a una carpeta en myZipFile.write, obtengo

IOError: [Errno 13] Permiso denegado: ''.. / packed / bin''

Cualquier ayuda es muy bienvenida.

Pregunta relacionada: ¿Cómo puedo comprimir el contenido de una carpeta usando Python (versión 2.5)?


Aquí está el código editado que ejecuté. Se basa en el código anterior, tomado de la lista de correo. Agregué las importaciones e hice una rutina principal. También corté el violín con el nombre de archivo de salida para acortar el código.

#!/usr/bin/env python import os, zipfile, glob, sys def addFolderToZip(myZipFile,folder): folder = folder.encode(''ascii'') #convert path to ascii for ZipFile Method for file in glob.glob(folder+"/*"): if os.path.isfile(file): print file myZipFile.write(file, os.path.basename(file), zipfile.ZIP_DEFLATED) elif os.path.isdir(file): addFolderToZip(myZipFile,file) def createZipFile(filename,files,folders): myZipFile = zipfile.ZipFile( filename, "w" ) # Open the zip file for writing for file in files: file = file.encode(''ascii'') #convert path to ascii for ZipFile Method if os.path.isfile(file): (filepath, filename) = os.path.split(file) myZipFile.write( file, filename, zipfile.ZIP_DEFLATED ) for folder in folders: addFolderToZip(myZipFile,folder) myZipFile.close() return (1,filename) if __name__=="__main__": #put everything in sys.argv[1] in out.zip, skip files print createZipFile("out.zip", [], sys.argv[1])

En el trabajo, en mi cuadro de Windows, este código funcionaba bien pero no creaba ninguna "carpeta" en el archivo zip. Al menos recuerdo que sí. Ahora en casa, en mi caja de Linux, el archivo zip creado parece ser malo:

$ unzip -l out.zip Archive: out.zip End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. unzip: cannot find zipfile directory in one of out.zip or out.zip.zip, and cannot find out.zip.ZIP, period.

No sé si accidentalmente rompí el código, creo que es lo mismo. ¿Problemas con la plataforma cruzada? De cualquier manera, no está relacionado con mi pregunta original; obteniendo carpetas en el archivo zip. Solo quería publicar el código que realmente ejecuté, no el código en el que basé mi código.


Un archivo zip no tiene estructura de directorio, solo tiene un montón de nombres de rutas y sus contenidos. Estos nombres de ruta deben ser relativos a una carpeta raíz imaginaria (el archivo ZIP en sí). Los prefijos "../" no tienen un significado definido en un archivo zip.

Considere que tiene un archivo, y desea almacenarlo en una "carpeta" dentro de un archivo zip. Todo lo que tienes que hacer es ponerle un nombre al nombre del archivo cuando guardes el archivo en el archivo zip:

zipi= zipfile.ZipInfo() zipi.filename= "folder/a" # this is what you want zipi.date_time= time.localtime(os.path.getmtime("a"))[:6] zipi.compress_type= zipfile.ZIP_DEFLATED filedata= open("a", "rb").read() zipfile1.writestr(zipi, filedata) # zipfile1 is a zipfile.ZipFile instance

No conozco ninguna implementación ZIP que permita la inclusión de una carpeta vacía en un archivo ZIP. Puedo pensar en una solución temporal (almacenar un nombre de archivo ficticio en la "carpeta" zip, que se debe ignorar en la extracción), pero no es portátil en todas las implementaciones.


después de agregar algunas importaciones, su código funciona bien para mí, ¿cómo se llama a la secuencia de comandos, tal vez podría decirnos la estructura de la carpeta del directorio ''.. / packed / bin''.

Llamé a tu código con los siguientes argumentos:

planName=''test.zip'' files=[''z.py'',] folders=[''c://temp''] (success,filename)=createZipFile(planName,files,folders)

`


Ok, después de haber entendido lo que quieres, es tan simple como usar el segundo argumento de zipfile.write , donde puedes usar lo que quieras:

import zipfile myZipFile = zipfile.ZipFile("zip.zip", "w" ) myZipFile.write("test.py", "dir//test.py", zipfile.ZIP_DEFLATED )

crea un archivo zip donde test.py se extraería a un directorio llamado dir

EDITAR: una vez tuve que crear un directorio vacío en un archivo zip: es posible. después del código anterior simplemente elimine el archivo test.py del archivo zip, el archivo se ha ido, pero el directorio vacío permanece.


Cuando quieras crear una carpeta vacía, puedes hacerlo así:

storage = api.Storage.open("empty_folder.zip","w") res = storage.open_resource("hannu//","w") storage.close()

La carpeta no se muestra en winextractor, pero cuando la extrae se muestra.


aquí está mi función que uso para comprimir una carpeta:

import os import os.path import zipfile def zip_dir(dirpath, zippath): fzip = zipfile.ZipFile(zippath, ''w'', zipfile.ZIP_DEFLATED) basedir = os.path.dirname(dirpath) + ''/'' for root, dirs, files in os.walk(dirpath): if os.path.basename(root)[0] == ''.'': continue #skip hidden directories dirname = root.replace(basedir, '''') for f in files: if f[-1] == ''~'' or (f[0] == ''.'' and f != ''.htaccess''): #skip backup files and all hidden files except .htaccess continue fzip.write(root + ''/'' + f, dirname + ''/'' + f) fzip.close()


¡Muchas gracias por esta útil función! Lo encontré muy útil ya que también estaba buscando ayuda. Sin embargo, tal vez sería útil cambiarlo un poco para que

basedir = os.path.dirname(dirpath) + ''/''

sería

basedir = os.path.dirname(dirpath + ''/'')

Porque encontré que si quiero comprimir la carpeta ''Ejemplo'' que se encuentra en ''C: / carpeta / ruta / notWanted / a / zip / Example'',

Me metí en Windows:

dirpath = ''C:/folder/path/notWanted/to/zip/Example'' basedir = ''C:/folder/path/notWanted/to/zip/Example/'' dirname = ''C:/folder/path/notWanted/to/zip/Example/Example/Subfolder_etc''

Pero supongo que tu código debería dar

dirpath = ''C:/folder/path/notWanted/to/zip/Example'' basedir = ''C:/folder/path/notWanted/to/zip/Example/' dirname = ''/Subfolder_etc''


A continuación se muestra un código para comprimir un directorio completo en un archivo zip.

Esto parece funcionar bien al crear archivos zip tanto en Windows como en Linux. Los archivos de salida parecen extraerse correctamente en Windows (característica incorporada Carpetas comprimidas, WinZip y 7-Zip) y Linux. Sin embargo, los directorios vacíos en un archivo zip parecen ser un problema espinoso. La siguiente solución parece funcionar, pero la salida de "zipinfo" en Linux es preocupante. Además, los permisos de directorio no están configurados correctamente para los directorios vacíos en el archivo zip. Esto parece requerir una investigación más a fondo.

Obtuve información de este hilo de revisiones de velocidad y este hilo de la lista de correo de python .

Tenga en cuenta que esta función está diseñada para colocar archivos en el archivo zip sin directorio principal o solo uno principal, por lo que recortará los directorios principales en las rutas del sistema de archivos y no los incluirá dentro de las rutas de archivo zip. Este es generalmente el caso cuando desea simplemente tomar un directorio y convertirlo en un archivo zip que se puede extraer en diferentes ubicaciones.

Argumentos de palabras clave:

dirPath - ruta de la cadena al directorio a archivar. Este es el único argumento requerido. Puede ser absoluto o relativo, pero solo uno o cero directorios principales se incluirán en el archivo zip.

zipFilePath: ruta de la cadena al archivo zip de salida. Esta puede ser una ruta absoluta o relativa. Si el archivo zip ya existe, se actualizará. Si no, será creado. Si desea reemplazarlo desde cero, bórrelo antes de llamar a esta función. (el valor predeterminado se calcula como dirPath + ".zip")

includeDirInZip - boolean que indica si el directorio de nivel superior debe incluirse en el archivo u omitirse. (predeterminado True)

(Tenga en cuenta que parece no imprimir bastante mi python con cadenas de comillas triples, por lo que acabo de convertir mis cadenas de documentos al texto de la publicación aquí)

#!/usr/bin/python import os import zipfile def zipdir(dirPath=None, zipFilePath=None, includeDirInZip=True): if not zipFilePath: zipFilePath = dirPath + ".zip" if not os.path.isdir(dirPath): raise OSError("dirPath argument must point to a directory. " "''%s'' does not." % dirPath) parentDir, dirToZip = os.path.split(dirPath) #Little nested function to prepare the proper archive path def trimPath(path): archivePath = path.replace(parentDir, "", 1) if parentDir: archivePath = archivePath.replace(os.path.sep, "", 1) if not includeDirInZip: archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1) return os.path.normcase(archivePath) outFile = zipfile.ZipFile(zipFilePath, "w", compression=zipfile.ZIP_DEFLATED) for (archiveDirPath, dirNames, fileNames) in os.walk(dirPath): for fileName in fileNames: filePath = os.path.join(archiveDirPath, fileName) outFile.write(filePath, trimPath(filePath)) #Make sure we get empty directories as well if not fileNames and not dirNames: zipInfo = zipfile.ZipInfo(trimPath(archiveDirPath) + "/") #some web sites suggest doing #zipInfo.external_attr = 16 #or #zipInfo.external_attr = 48 #Here to allow for inserting an empty directory. Still TBD/TODO. outFile.writestr(zipInfo, "") outFile.close()

Aquí hay algunos usos de muestra. Tenga en cuenta que si su argumento dirPath tiene varios directorios principales, solo el ÚLTIMO se incluirá de manera predeterminada. Pase includeDirInZip = False para omitir todos los directorios principales.

zipdir("foo") #Just give it a dir and get a .zip file zipdir("foo", "foo2.zip") #Get a .zip file with a specific file name zipdir("foo", "foo3nodir.zip", False) #Omit the top level directory zipdir("../test1/foo", "foo4nopardirs.zip")


Si miras un archivo zip creado con Info-ZIP, verás que los directorios están listados:

$ zip foo.zip -r foo adding: foo/ (stored 0%) adding: foo/foo.jpg (deflated 84%) $ less foo.zip Archive: foo.zip Length Method Size Cmpr Date Time CRC-32 Name -------- ------ ------- ---- ---------- ----- -------- ---- 0 Stored 0 0% 2013-08-18 14:32 00000000 foo/ 476320 Defl:N 77941 84% 2013-08-18 14:31 55a52268 foo/foo.jpg -------- ------- --- ------- 476320 77941 84% 2 files

Tenga en cuenta que la entrada del directorio tiene una longitud cero y no está comprimida. Parece que puedes lograr lo mismo con Python escribiendo el directorio por nombre, pero forzándolo a no usar compresión.

if os.path.isdir(name): zf.write(name, arcname=arcname, compress_type=zipfile.ZIP_STORED) else: zf.write(name, arcname=arcname, compress_type=zipfile.ZIP_DEFLATED)

Vale la pena asegurarse de que arcname termine en a / .


import zipfile import os class ZipUtilities: def toZip(self, file, filename): zip_file = zipfile.ZipFile(filename, ''w'') if os.path.isfile(file): zip_file.write(file) else: self.addFolderToZip(zip_file, file) zip_file.close() def addFolderToZip(self, zip_file, folder): for file in os.listdir(folder): full_path = os.path.join(folder, file) if os.path.isfile(full_path): print ''File added: '' + str(full_path) zip_file.write(full_path) elif os.path.isdir(full_path): print ''Entering folder: '' + str(full_path) self.addFolderToZip(zip_file, full_path) def main(): utilities = ZipUtilities() filename = ''TEMP.zip'' directory = ''TEMP'' utilities.toZip(directory, filename) main()

Estoy corriendo:

python tozip.py

Este es el registro:

havok@fireshield:~$ python tozip.py File added: TEMP/NARF (7ª copia) Entering folder: TEMP/TEMP2 File added: TEMP/TEMP2/NERF (otra copia) File added: TEMP/TEMP2/NERF (copia) File added: TEMP/TEMP2/NARF File added: TEMP/TEMP2/NARF (copia) File added: TEMP/TEMP2/NARF (otra copia) Entering folder: TEMP/TEMP2/TEMP3 File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL File added: TEMP/TEMP2/TEMP3/DOCUMENTO DEL FINAL (copia) File added: TEMP/TEMP2/NERF File added: TEMP/NARF (copia) (otra copia) File added: TEMP/NARF (copia) (copia) File added: TEMP/NARF (6ª copia) File added: TEMP/NERF (copia) (otra copia) File added: TEMP/NERF (4ª copia) File added: TEMP/NERF (otra copia) File added: TEMP/NERF (3ª copia) File added: TEMP/NERF (6ª copia) File added: TEMP/NERF (copia) File added: TEMP/NERF (5ª copia) File added: TEMP/NARF (8ª copia) File added: TEMP/NARF (3ª copia) File added: TEMP/NARF (5ª copia) File added: TEMP/NERF (copia) (3ª copia) File added: TEMP/NARF File added: TEMP/NERF (copia) (copia) File added: TEMP/NERF (8ª copia) File added: TEMP/NERF (7ª copia) File added: TEMP/NARF (copia) File added: TEMP/NARF (otra copia) File added: TEMP/NARF (4ª copia) File added: TEMP/NERF File added: TEMP/NARF (copia) (3ª copia)

Como puede ver, funciona, el archivo también está bien. Esta es una función recursiva que puede comprimir una carpeta completa. El único problema es que no crea una carpeta vacía.

Aclamaciones.


import os import zipfile zf = zipfile.ZipFile("file.zip", "w") for file in os.listdir(os.curdir): if not file.endswith(''.zip'') and os.path.isfile(os.curdir+''/''+file): print file zf.write(file) elif os.path.isdir(os.curdir+''/''+file): print f for f in os.listdir(os.curdir+''/''+file): zf.write(file+''//'+f) zf.close()


También puedes usar shutil

import shutil zip_name = ''path/to/zip_file'' directory_name = ''path/to/directory'' # Create ''path/to/zip_file.zip'' shutil.make_archive(zip_name, ''zip'', directory_name)

Esto pondrá toda la carpeta en el zip.