compress - Crear.zip en Python?
comprimir python (3)
El método zipfile.write()
toma un argumento arcname
opcional que especifica cuál debe ser el nombre del archivo dentro del archivo zip.
Puede usar esto para quitarle la ruta a src
al comienzo. Aquí utilizo os.path.abspath()
para asegurarme de que tanto src
como el nombre de archivo devuelto por os.walk()
tienen un prefijo común.
#!/usr/bin/env python2.7
import os
import zipfile
def zip(src, dst):
zf = zipfile.ZipFile("%s.zip" % (dst), "w", zipfile.ZIP_DEFLATED)
abs_src = os.path.abspath(src)
for dirname, subdirs, files in os.walk(src):
for filename in files:
absname = os.path.abspath(os.path.join(dirname, filename))
arcname = absname[len(abs_src) + 1:]
print ''zipping %s as %s'' % (os.path.join(dirname, filename),
arcname)
zf.write(absname, arcname)
zf.close()
zip("src", "dst")
Con una estructura de directorios como esta:
src
└── a
├── b
│ └── bar
└── foo
El script imprime:
zipping src/a/foo as a/foo
zipping src/a/b/bar as a/b/bar
Y el contenido del archivo zip resultante es:
Archive: dst.zip
Length Date Time Name
-------- ---- ---- ----
0 01-28-13 11:36 a/foo
0 01-28-13 11:36 a/b/bar
-------- -------
0 2 files
Intento crear una función en mi script que ajuste el contenido de un directorio fuente dado ( src
) a un archivo zip ( dst
). Por ejemplo, zip(''/path/to/dir'', ''/path/to/file.zip'')
, donde /path/to/dir
es un directorio, y /path/to/file.zip
no existe todavía. No quiero comprimir el directorio en sí, esto marca la diferencia en mi caso. Quiero comprimir los archivos (y subdirectorios) en el directorio. Esto es lo que intento:
def zip(src, dst):
zf = zipfile.ZipFile("%s.zip" % (dst), "w")
for dirname, subdirs, files in os.walk(src):
zf.write(dirname)
for filename in files:
zf.write(os.path.join(dirname, filename))
zf.close()
Esto crea un zip que es esencialmente /
. Por ejemplo, si comprimí /path/to/dir
, al extraer el archivo zip creé un directorio con "ruta" en él, con "a" en ese directorio, etc.
¿Alguien tiene una función que no causa este problema?
No puedo enfatizar esto lo suficiente, necesita comprimir los archivos en el directorio, no el directorio en sí.
Por lo que puedo decir, estás cerca. Puede usar dirname
y basename
para asegurarse de que está utilizando el nombre de la ruta correcta:
>>> os.path.dirname("/path/to/dst")
''/path/to''
>>> os.path.basename("/path/to/dst")
''dst''
Luego, usando chdir
puedes asegurarte de que estás en el padre para que las rutas sean relativas.
def zip(src, dst):
parent = os.path.dirname(dst)
folder = os.path.basename(dst)
os.chdir(parent):
for dirname, subdirs, filenames in os.walk(folder):
...
Esto crea:
dst/a.txt
dst/b
dst/b/c.txt
...etc...
Si no desea incluir el nombre "dst", simplemente puede hacer os.chdir(dst)
y luego os.walk(''.'')
.
Espero que ayude.
Use el parámetro arcname
para controlar el nombre / ruta en el archivo zip.
Por ejemplo, para un archivo zip que contiene solo archivos, no hay directorios:
zf.write(os.path.join(dirname, filename), arcname=filename)
O inventar un nuevo directorio dentro del archivo zip:
zf.write(os.path.join(dirname, filename), arcname=os.path.join("my_zip_dir", filename))