Ajouter des dossiers à un fichier zip en utilisant python
je veux créer un fichier zip. Ajoutez un dossier au fichier zip, puis ajoutez un tas de fichiers à ce dossier.
Si je veux retrouver avec un fichier zip avec un seul dossier avec des fichiers en.
Je ne sais pas si c'est une mauvaise pratique d'avoir des dossiers dans des fichiers zip ou quelque chose mais google ne me donne rien sur le sujet.
j'ai commencé par ceci:
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);
tiré de: http://mail.python.org/pipermail/python-list/2006-August/396166.html
Qui se débarrasse de tous les dossiers et met tous les fichiers dans le dossier cible (et ses sous-dossiers) dans un seul fichier zip. Je ne pourrais pas l'obtenir pour ajouter un dossier entier.
si j'alimente le chemin vers un dossier dans myZipFile.Ecrivez, je reçois
IOError: [Errno 13] Permission refusée:"..paniersbin'
toute l'aide est avec beaucoup de satisfaction.
question connexe: Comment puis-je zip le contenu d'un dossier en utilisant python (version 2.5)?
12 réponses
Ok, après j'ai compris ce que vous voulez, c'est aussi simple que d'utiliser le deuxième argument de zipfile.write
, où vous pouvez utiliser ce que vous voulez:
import zipfile
myZipFile = zipfile.ZipFile("zip.zip", "w" )
myZipFile.write("test.py", "dir\test.py", zipfile.ZIP_DEFLATED )
crée un fichier zip où test.py
serait extrait dans un répertoire appelé dir
EDIT: Une fois, j'ai dû créer un répertoire vide dans un fichier zip: c'est possible. après le code ci-dessus il suffit de supprimer le fichier test.py du zipfile, le fichier a disparu, mais le vide répertoire des séjours.
vous pouvez également utiliser 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)
cela placera tout le dossier dans le zip.
un fichier zip n'a pas de structure de répertoire, il a juste un tas de noms de chemin et leur contenu. Ces noms de chemin doivent être relatifs à un dossier racine imaginaire (le fichier ZIP lui-même). "../" les préfixes ont pas de signification définie dans un fichier zip.
Considérez que vous avez un fichier, a
et vous souhaitez le stocker dans un "dossier" à l'intérieur d'un fichier zip. Tout ce que vous avez à faire est de préfixer le nom du fichier avec un nom de dossier lors du stockage du fichier dans le zipfile:
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
Je ne connais aucune implémentation ZIP permettant l'inclusion d'un dossier vide dans un fichier ZIP. Je peux penser à une solution de rechange (stocker un dummy nom de fichier dans le "dossier" zip qui devrait être ignoré lors de l'extraction), mais pas portable à travers les implémentations.
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()
je suis en cours d'exécution:
python tozip.py
C'est le log:
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)
comme vous pouvez le voir, il fonctionne, l'archive est ok aussi. C'est une fonction récursive qui peut compresser un dossier entier. Le seul problème est qu'il ne crée pas de dossier vide.
santé.
ci-dessous est un code pour zipper un répertoire entier dans un zipfile.
cela semble fonctionner correctement en créant des fichiers zip sur windows et linux. Sortie les fichiers semblent extraire correctement sur windows (intégré dans les dossiers compressés fonctionnalité, WinZip, et 7-Zip) et linux. Cependant, les répertoires vides dans un fichier zip apparaissent une question épineuse. La solution ci-dessous semble fonctionner, mais la sortie de "zipinfo" sur linux. Aussi les autorisations de répertoire ne sont pas définir correctement pour les répertoires vides dans l'archive zip. Cela semble exiger un peu plus dans la profondeur de la recherche.
j'ai eu quelques infos de ce fil de commentaires de velocity et ce fil de liste de diffusion de python .
Notez que cette fonction est conçue pour mettre des fichiers dans l'archive zip avec aucun répertoire parent ou un seul parent directory, donc il va couper tout principaux répertoires du système de fichiers chemins et de ne pas les inclure à l'intérieur de la chemins d'archives zip. C'est généralement le cas lorsque vous voulez juste prendre un répertoire et le faire dans un fichier zip qui peut être extrait dans différents emplacement.
mots clés arguments:
dirPath -- string path vers le répertoire de l'archive. C'est la seule l'argument requis. Il peut être absolu ou relatif, mais seulement un ou zéro principaux répertoires seront inclus dans l'archive zip.
zipFilePath -- chemin de chaîne à la sortie de fichier zip. Cela peut être un absolu ou chemin d'accès relatif. Si le fichier zip existe déjà, il sera mis à jour. Si pas, il sera créé. Si vous voulez le remplacer à partir de zéro, supprimez-le avant l'appel à cette fonction. (la valeur par défaut est dirPath + ".zip")
includeDirInZip -- booléen indiquant si le répertoire de niveau supérieur devrait être inclus dans l'archive ou omis. (par défaut à True)
(noter que StackOverflow semble ne pas réussir à imprimer mon python avec Triple cordes citées, donc je viens de convertir mes cordes doc en texte post ici)
#!/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()
voici quelques exemples d'utilisations. Notez que si votre argument dirPath contient plusieurs répertoires principaux, seul le dernier sera inclus par défaut. Pass includeDirInZip=False pour omettre tous les répertoires principaux.
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")
voici ma fonction que j'utilise pour compresser un dossier:
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()
après avoir ajouté quelques importations votre code fonctionne très bien pour moi, comment appelez-vous le script, peut-être pourriez-vous nous dire la structure du dossier de la '..\paniers\bin " du dossier.
j'ai appelé votre code avec les arguments suivants:
planName='test.zip'
files=['z.py',]
folders=['c:\temp']
(success,filename)=createZipFile(planName,files,folders)
`
si vous regardez un fichier zip créé avec Info-ZIP, vous verrez que les répertoires sont bien listés:
$ 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
notez que l'entrée du répertoire a une longueur zéro et n'est pas compressée. Il semble que vous pouvez obtenir la même chose avec Python en écrivant le répertoire par nom, mais en le forçant à ne pas utiliser la compression.
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)
Il pourrait être utile de faire assurer arcname
se termine par un /
.
est le code que j'ai utilisé. Il est basé sur le code ci-dessus, tiré de la liste de diffusion. J'ai ajouté les importations et fait une routine principale. J'ai également coupé les jongler avec le nom de fichier de sortie pour rendre le code plus court.
#!/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])
au travail, sur ma fenêtre Windows, ce code fonctionnait bien mais ne créait pas de" dossiers " dans le fichier zip. Au moins je me souviens qu'il a fait. Maintenant à la maison, sur mon Linux, le fichier zip créé semble être mauvais:
$ 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.
I ne sais pas si j'ai accidentellement cassé le code, je pense que c'est la même chose. Compatible questions? Quoi qu'il en soit, ce n'est pas lié à ma question d'origine; obtenir des dossiers dans le fichier zip. Je voulais juste poster le code que j'ai réellement couru, pas le code sur lequel j'ai basé mon code.
Merci beaucoup wery pour cette fonction utile! Je l'ai trouvé très utile car je cherchais aussi de l'aide. Cependant, il serait peut-être utile de le changer un peu pour que
basedir = os.path.dirname(dirpath) + '/'
serait
basedir = os.path.dirname(dirpath + '/')
parce que j'ai trouvé que si je veux zip dossier 'exemple' qui est situé à 'C:\folder\path\notWanted\to\zip\Example",
je suis sous 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'
mais je suppose votre code devrait indiquer
dirpath = 'C:\folder\path\notWanted\to\zip\Example'
basedir = 'C:\folder\path\notWanted\to\zip\Example\'
dirname = '\Subfolder_etc'
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()
Lorsque vous voulez créer un dossier vide, vous pouvez le faire comme ceci:
storage = api.Storage.open("empty_folder.zip","w")
res = storage.open_resource("hannu//","w")
storage.close()
dossier ne pas afficher dans winextractor, mais quand vous l'extrayez il est montré.