使用shutil.make_archive()压缩目录,同时保留目录结构

G W*_*ner 24 python directory zip shutil

我正在尝试将名为test_dicomszip文件的目录压缩为test_dicoms.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
Run Code Online (Sandbox Code Playgroud)

Rob*_*obᵩ 32

使用文档中的术语,您指定了root_dir,但未指定base_dir.尝试像这样指定base_dir:

shutil.make_archive('/home/code/test_dicoms',
                    'zip',
                    '/home/code/',
                    'test_dicoms')
Run Code Online (Sandbox Code Playgroud)

要回答第二个问题,这取决于您使用的Python版本.从Python 3.4开始,默认情况下将提供ZIP64扩展.在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)
Run Code Online (Sandbox Code Playgroud)

参考:


sea*_*han 8

我自己写了一个包装函数,因为shutil.make_archive太混乱了,无法使用。

这是http://www.seanbehan.com/how-to-use-python-shutil-make_archive-to-zip-up-a-directory-recursively-includes-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')
Run Code Online (Sandbox Code Playgroud)


Mak*_*e42 6

我认为,我可以通过删除文件移动来改进 Seanbehan 的答案:

def make_archive(source, destination):
    base_name = '.'.join(destination.split('.')[:-1])
    format = destination.split('.')[-1]
    root_dir = os.path.dirname(source)
    base_dir = os.path.basename(source.strip(os.sep))
    shutil.make_archive(base_name, format, root_dir, base_dir)
Run Code Online (Sandbox Code Playgroud)


iru*_*yak 5

基本上有两种使用方法shutil:您可以尝试理解其背后的逻辑,或者您可以只使用一个示例。我在这里找不到示例,所以我尝试创建自己的示例。

\n

; 长话短说。运行shutil.make_archive('dir1_arc', 'zip', root_dir='dir1')shutil.make_archive('dir1_arc', 'zip', base_dir='dir1')或 只是shutil.make_archive('dir1_arc', 'zip', 'dir1')temp.

\n

假设你有~/temp/dir1

\n
temp $ tree dir1\ndir1\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dir11\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file11\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file12\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file13\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 dir1_arc.zip\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file1\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 file2\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file3\n
Run Code Online (Sandbox Code Playgroud)\n

如何创建 的档案dir1?放base_name='dir1_arc'format='zip'。好吧,你有很多 选择:

\n
    \n
  • cd进入dir1并运行shutil.make_archive(base_name=base_name, format=format);它将dir1_arc.zip在里面创建一个档案dir1;唯一的问题是你会得到一个奇怪的行为:在你的档案中你会发现 file dir1_arc.zip
  • \n
  • temp运行shutil.make_archive(base_name=base_name, format=format, base_dir='dir1');您将进入可以解压缩的dir1_arc.zip内部;默认为;tempdir1root_dirtemp
  • \n
  • ~运行shutil.make_archive(base_name=base_name, format=format, root_dir='temp', base_dir='dir1');您将再次获得文件,但这次是在~目录内;
  • \n
  • 创建另一个目录并temp2~其中运行:shutil.make_archive(base_name=base_name, format=format, root_dir='../temp', base_dir='dir1'); 您将在此文件夹中找到您的存档temp2
  • \n
\n

您可以shutil在不指定参数的情况下运行吗?你可以。逃离temp shutil.make_archive('dir1_arc', 'zip', 'dir1')。这与运行相同shutil.make_archive('dir1_arc', 'zip', root_dir='dir1')。在这种情况下我们能说什么呢base_dir?从文档来看,没有那么多。从源码中我们可以看出:

\n
if root_dir is not None:\n  os.chdir(root_dir)\n\nif base_dir is None:\n        base_dir = os.curdir \n
Run Code Online (Sandbox Code Playgroud)\n

所以在我们的例子中base_dirdir1. 我们可以继续提问。

\n