J'essaie de créer une fonction dans mon script qui zippe le contenu d'un répertoire source donné (src
) dans un fichier Zip (dst
). Par exemple, Zip('/path/to/dir', '/path/to/file.Zip')
, où /path/to/dir
est un répertoire et /path/to/file.Zip
n'existe pas encore. Je ne pas veux compresser le répertoire lui-même, cela fait toute la différence dans mon cas. Je veux compresser les fichiers (et sous-répertoires) dans le répertoire. Voici ce que j'essaie:
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()
Cela crée un Zip qui est essentiellement /
. Par exemple, si j'ai zippé /path/to/dir
, extraire le Zip crée un répertoire contenant "chemin", avec "à" dans ce répertoire, etc.
Quelqu'un at-il une fonction qui ne cause pas ce problème?
Je ne saurais trop insister là-dessus, il a besoin pour compresser les fichiers dans le répertoire, pas le directoy lui-même.
La méthode zipfile.write()
prend un argument arcname
facultatif qui spécifie le nom du fichier à l'intérieur du fichier zip.
Vous pouvez l'utiliser pour supprimer le chemin vers src
au début. Ici, j'utilise os.path.abspath()
pour m'assurer que src
et le nom de fichier renvoyé par os.walk()
ont un préfixe commun.
#!/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")
Avec une structure de répertoires comme celle-ci:
src
└── a
├── b
│ └── bar
└── foo
Le script imprime:
zipping src/a/foo as a/foo
zipping src/a/b/bar as a/b/bar
Et le contenu du fichier Zip résultant est:
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
D'après ce que je peux vous dire, vous êtes proche. Vous pouvez utiliser dirname
et basename
pour vous assurer que vous saisissez le bon nom de chemin:
>>> os.path.dirname("/path/to/dst")
'/path/to'
>>> os.path.basename("/path/to/dst")
'dst'
Ensuite, en utilisant chdir
, vous pouvez vous assurer que vous êtes dans le parent afin que les chemins d'accès soient relatifs.
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):
...
Cela crée:
dst/a.txt
dst/b
dst/b/c.txt
...etc...
Si vous ne souhaitez pas inclure le nom "dst", vous pouvez simplement faire os.chdir(dst)
puis os.walk('.')
.
J'espère que ça t'as aidé.
Utilisez le paramètre arcname
pour contrôler le nom/chemin dans le fichier Zip.
Par exemple, pour un fichier Zip qui ne contient que des fichiers, pas de répertoires:
zf.write(os.path.join(dirname, filename), arcname=filename)
Ou pour inventer un nouveau répertoire dans le fichier Zip:
zf.write(os.path.join(dirname, filename), arcname=os.path.join("my_Zip_dir", filename))