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.