我尝试使用以下代码将名为test_dicoms
的目录压缩到名为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
答案 0 :(得分:29)
使用文档中的条款,您指定了 root_dir ,但未指定 base_dir 。尝试指定 base_dir ,如下所示:
shutil.make_archive('/home/code/test_dicoms',
'zip',
'/home/code/',
'test_dicoms')
要回答第二个问题,这取决于您使用的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)
参考:
答案 1 :(得分:5)
我自己编写了一个包装函数,因为shutil.make_archive太难以使用了。
只是代码..
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 :(得分:1)
使用shutil
基本上有两种方法:您可以尝试了解其背后的逻辑,也可以仅举一个示例。我在这里找不到示例,所以我尝试创建自己的示例。
; TLDR。从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
。
假设您有~/temp/dir1
:
temp $ tree dir1
dir1
├── dir11
│ ├── file11
│ ├── file12
│ └── file13
├── dir1_arc.zip
├── file1
├── file2
└── file3
如何创建dir1
的存档?设置base_name='dir1_arc'
,format='zip'
。嗯,您有很多选择:
cd
进入dir1
并运行shutil.make_archive(base_name=base_name, format=format)
;它将在dir1_arc.zip
内创建档案dir1
;唯一的问题是您会遇到奇怪的行为:在存档中,您会找到文件dir1_arc.zip
; temp
开始运行shutil.make_archive(base_name=base_name, format=format, base_dir='dir1')
;您将在dir1_arc.zip
中看到temp
,可以将其解压缩到dir1
中; root_dir
默认为temp
; ~
开始运行shutil.make_archive(base_name=base_name, format=format, root_dir='temp', base_dir='dir1')
;您将再次获取文件,但是这次在~
目录中; temp2
中创建另一个目录~
并在其中运行:shutil.make_archive(base_name=base_name, format=format, root_dir='../temp', base_dir='dir1')
;您将在此temp2
文件夹中找到归档文件; 是否可以在不指定参数的情况下运行shutil
?您可以。从temp
shutil.make_archive('dir1_arc', 'zip', 'dir1')
开始运行。这与运行shutil.make_archive('dir1_arc', 'zip', root_dir='dir1')
相同。在这种情况下,我们能对base_dir
说些什么?从文档中得到的不多。从源代码中,我们可能会看到:
if root_dir is not None:
os.chdir(root_dir)
if base_dir is None:
base_dir = os.curdir
因此,在我们的情况下,base_dir
是dir1
。而且我们可以继续提出问题。
答案 3 :(得分:0)
我在某些带有“.”的路径上遇到路径拆分问题句号,我发现有一个默认为“zip”的可选格式很方便,并且仍然允许您覆盖其他格式并且不太容易出错。
for (int i = 1; i < N; i++) {
for (int j = i; j < N; j += i) {
ans[j].push_back(i);
}
}
import os
import shutil
from shutil import make_archive
def make_archive(source, destination, format='zip'):
import os
import shutil
from shutil import make_archive
base, name = os.path.split(destination)
archive_from = os.path.dirname(source)
archive_to = os.path.basename(source.strip(os.sep))
print(f'Source: {source}\nDestination: {destination}\nArchive From: {archive_from}\nArchive To: {archive_to}\n')
shutil.make_archive(name, format, archive_from, archive_to)
shutil.move('%s.%s' % (name, format), destination)
特别感谢 seanbehan 的原始回答,否则我会在酱汁中迷失更长时间。