web-dev-qa-db-ja.com

shutil.make_archive()を使用してディレクトリ構造を保存しながらディレクトリを圧縮する

次のコードを使用して、test_dicomsというディレクトリをtest_dicoms.Zipという名前のZipファイルにZipしようとしています。

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

問題は、解凍すると、/test_dicoms/にあったすべてのファイルが、フォルダー/home/code/ではなく/test_dicoms/に抽出され、すべてのファイルに/home/code/に抽出されるファイルが含まれることです。したがって、/test_dicoms/にはfoo.txtというファイルがあり、foo.txtではなく/home/code/foo.txtのパスを/home/code/test_dicoms/foo.txtに圧縮して解凍します。どうすれば修正できますか?また、私が作業しているディレクトリのいくつかは非常に大きいです。 Zip64にするためにコードに何かを追加する必要がありますか、それとも自動的にそれを行うのに十分な機能ですか

現在作成されているアーカイブには次のものがあります。

[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
23
G Warner

ドキュメントの用語を使用して、root_dirを指定しましたが、base_dir。次のようにbase_dirを指定してみてください:

_shutil.make_archive('/home/code/test_dicoms',
                    'Zip',
                    '/home/code/',
                    'test_dicoms')
_

2番目の質問に答えるには、使用しているPythonのバージョンに依存します。Python 3.4から、Z​​ip64拡張機能はデフォルトで利用可能になります。 Python 3.4、_make_archive_は自動的にZip64拡張子のファイルを作成しません。古いバージョンのPythonを使用していてZip64が必要な場合は、基になるzipfile.ZipFile()を直接呼び出すことができます。

zipfile.ZipFile()をバイパスして、shutil.make_archive()を直接使用することを選択した場合の例を次に示します。

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

参照:

31
Robᵩ

Shutil.make_archiveを使用するのはわかりにくいため、自分でラッパー関数を作成しました。

ここにあります http://www.seanbehan.com/how-to-use-python-shutil-make_archive-to-Zip-up-a-directory-recursively-include-the-root-folder/

そして、ただのコード..

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')
7
seanbehan