web-dev-qa-db-fra.com

Compression du répertoire à l’aide de la commande shutil.make_archive () tout en préservant la structure du répertoire

J'essaie de compresser un répertoire appelé test_dicoms dans un fichier Zip nommé test_dicoms.Zip à l'aide du code suivant:

shutil.make_archive('/home/code/test_dicoms','Zip','/home/code/test_dicoms')

Le problème est que lorsque je décompresse le fichier, tous les fichiers qui étaient dans /test_dicoms/ sont extraits dans /home/code/ au lieu du dossier /test_dicoms/ et tous les fichiers qu'il contient sont extraits dans /home/code/. Donc /test_dicoms/ a un fichier appelé foo.txt et après I Zip et décompresser le chemin de foo.txt est /home/code/foo.txt par opposition à /home/code/test_dicoms/foo.txt. Comment puis-je réparer ça? En outre, certains des répertoires avec lesquels je travaille sont très volumineux. Dois-je ajouter quelque chose à mon code pour le rendre Zip64 ou la fonction est-elle assez intelligente pour le faire automatiquement?

Voici ce qui est actuellement dans les archives créées:

[gwarner@jazz gwarner]$ unzip -l test_dicoms.Zip
Archive: test_dicoms.Zip
Length    Date       Time  Name
--------- ---------- ----- ----
    93324 09-17-2015 16:05 AAscout_b_000070
    93332 09-17-2015 16:05 AAscout_b_000125
    93332 09-17-2015 16:05 AAscout_b_000248
18
G Warner

En utilisant les termes de la documentation, vous avez spécifié un root_dir, mais pas un base_dir. Essayez de spécifier le base_dir comme ceci: 

shutil.make_archive('/home/code/test_dicoms',
                    'Zip',
                    '/home/code/',
                    'test_dicoms')

Pour répondre à votre deuxième question, cela dépend de la version de Python que vous utilisez. À partir de Python 3.4, les extensions Zip64 seront disponibles par défaut. Avant Python 3.4, make_archive ne créera pas automatiquement un fichier avec des extensions Zip64. Si vous utilisez une ancienne version de Python et que vous voulez Zip64, vous pouvez appeler directement la fonction zipfile.ZipFile() sous-jacente.

Si vous choisissez d'utiliser zipfile.ZipFile() directement, en contournant shutil.make_archive(), voici un exemple:

import zipfile
import os

d = '/home/code/test_dicoms'

os.chdir(os.path.dirname(d))
with zipfile.ZipFile(d + '.Zip',
                     "w",
                     zipfile.Zip_DEFLATED,
                     allowZip64=True) as zf:
    for root, _, filenames in os.walk(os.path.basename(d)):
        for name in filenames:
            name = os.path.join(root, name)
            name = os.path.normpath(name)
            zf.write(name, name)

Référence: 

28
Robᵩ

J'ai moi-même écrit une fonction wrapper parce que shutil.make_archive est trop compliqué à utiliser. 

Ici c'est http://www.seanbehan.com/how-to-use-python-shutil-make_archive-to-Zip-up-a-directory-recursively-inclosing-the-root-folder/

Et juste le code .. 

import os, shutil
def make_archive(source, destination):
        base = os.path.basename(destination)
        name = base.split('.')[0]
        format = base.split('.')[1]
        archive_from = os.path.dirname(source)
        archive_to = os.path.basename(source.strip(os.sep))
        shutil.make_archive(name, format, archive_from, archive_to)
        shutil.move('%s.%s'%(name,format), destination)

make_archive('/path/to/folder', '/path/to/folder.Zip')
2
seanbehan