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)?

39
demandé sur Community 2009-01-19 20:33:17

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.

42
répondu RSabet 2009-01-24 11:31:00

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.

50
répondu Gideon 2017-02-17 17:34:02

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.

11
répondu tzot 2009-01-19 21:34:13
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é.

7
répondu Community 2014-07-23 14:58:24

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")
4
répondu Mu Mind 2011-06-29 03:14:07

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()
3
répondu Dmitry Nedbaylo 2009-10-09 17:04:44

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)

`

2
répondu RSabet 2009-01-19 17:47:34

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 / .

2
répondu z0r 2013-08-18 04:41:39

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.

0
répondu Mizipzor 2009-01-19 22:26:04

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'
0
répondu note 2009-12-15 10:17:30
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()
0
répondu sohom 2014-09-17 19:32:24

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é.

-2
répondu 2009-03-24 08:06:09