如何创建目录的 zip 存档?
如何在 Python 中创建目录结构的 zip 存档?
How can I create a zip archive of a directory structure in Python?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
如何在 Python 中创建目录结构的 zip 存档?
How can I create a zip archive of a directory structure in Python?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(30)
最简单的方法是使用
shutil.make_archive
< /a>.它支持 zip 和 tar 格式。如果您需要做比压缩整个目录更复杂的事情(例如跳过某些文件),那么您需要深入研究
zipfile
模块,正如其他人建议的那样。The easiest way is to use
shutil.make_archive
. It supports both zip and tar formats.If you need to do something more complicated than zipping the whole directory (such as skipping certain files), then you'll need to dig into the
zipfile
module as others have suggested.正如其他人指出的那样,您应该使用 zipfile。该文档告诉您哪些功能可用,但并没有真正解释如何使用它们来压缩整个目录。我认为用一些示例代码来解释是最简单的:
As others have pointed out, you should use zipfile. The documentation tells you what functions are available, but doesn't really explain how you can use them to zip an entire directory. I think it's easiest to explain with some example code:
要将
mydirectory
的内容添加到新的 zip 文件,包括所有文件和子目录:To add the contents of
mydirectory
to a new zip file, including all files and subdirectories:在 Python 脚本中
在 Python 2.7+ 中,shutil 有一个 make_archive 函数。
这里,压缩档案将被命名为
zipfile_name.zip
。如果base_dir
距离root_dir
更远,它将排除不在base_dir
中的文件,但仍将父目录中的文件存档到 <代码>root_dir。我在使用 2.7 的 Cygwin 上测试时确实遇到了问题 - 它需要一个 root_dir 参数,用于 cwd:
从 shell 使用 Python
您可以使用 shell 中的 Python 来执行此操作,也可以使用
zipfile
模块: code>zipname 是您想要的目标文件的名称(如果需要,请添加
.zip
,它不会自动执行),sourcedir 是目录的路径。压缩 Python(或者只是不需要父目录):
如果您尝试使用
__init__.py
和__main__.py
压缩 python 包,并且您不需要父目录,它会
运行该包。 (请注意,您不能将子包作为压缩存档的入口点运行。)
压缩 Python 应用程序:
如果您有 python3.5+,并且特别想要压缩 Python 包,请使用 zipapp:
In a Python script
In Python 2.7+,
shutil
has amake_archive
function.Here the zipped archive will be named
zipfile_name.zip
. Ifbase_dir
is farther down fromroot_dir
it will exclude files not in thebase_dir
, but still archive the files in the parent dirs up to theroot_dir
.I did have an issue testing this on Cygwin with 2.7 - it wants a root_dir argument, for cwd:
Using Python from the shell
You can do this with Python from the shell also using the
zipfile
module:Where
zipname
is the name of the destination file you want (add.zip
if you want it, it won't do it automatically) and sourcedir is the path to the directory.Zipping up Python (or just don't want parent dir):
If you're trying to zip up a python package with a
__init__.py
and__main__.py
, and you don't want the parent dir, it'sAnd
would run the package. (Note that you can't run subpackages as the entry point from a zipped archive.)
Zipping a Python app:
If you have python3.5+, and specifically want to zip up a Python package, use zipapp:
此函数将递归地压缩目录树,压缩文件,并在存档中记录正确的相对文件名。归档条目与 zip -r output.zip source_dir 生成的条目相同。
This function will recursively zip up a directory tree, compressing the files, and recording the correct relative filenames in the archive. The archive entries are the same as those generated by
zip -r output.zip source_dir
.使用 python 3.9,
pathlib
&zipfile
模块您可以从系统中的任何位置创建 zip 文件。它很整洁,有打字功能,并且代码较少。
With python 3.9,
pathlib
&zipfile
module you can create a zip files from anywhere in the system.It is neat, typed, and has less code.
使用
pathlib
模块的现代 Python (3.6+)用于简洁的类似 OOP 的路径处理,以及pathlib。 Path.rglob()
用于递归通配符。据我所知,这相当于 George V. Reilly 的答案:压缩 zip,最上面的元素是一个目录,保留空目录,使用相对路径。注意:正如可选类型提示所示,
zip_name
不能是 Path 对象(将被修复在 3.6.2+ 中)。Modern Python (3.6+) using the
pathlib
module for concise OOP-like handling of paths, andpathlib.Path.rglob()
for recursive globbing. As far as I can tell, this is equivalent to George V. Reilly's answer: zips with compression, the topmost element is a directory, keeps empty dirs, uses relative paths.Note: as optional type hints indicate,
zip_name
can't be a Path object (would be fixed in 3.6.2+).使用shutil,它是python标准库集的一部分。
使用 Shutil 非常简单(参见下面的代码):
代码:
Use shutil, which is part of python standard library set.
Using shutil is so simple(see code below):
Code:
要向生成的 zip 文件添加压缩,请查看 这个链接。
您需要更改
:
For adding compression to the resulting zip file, check out this link.
You need to change:
to
要保留要归档的父目录下的文件夹层次结构:
To retain the folder hierarchy under the parent directory to be archived:
我对 Mark Byers 提供的代码进行了一些更改。如果有的话,下面的函数还将添加空目录。示例应该可以更清楚地说明添加到 zip 中的路径是什么。
上面是一个简单的函数,应该适用于简单的情况。你可以在我的要点中找到更优雅的课程:
https://gist.github.com/Eccenux/17526123107ca0ac28e6
I've made some changes to code given by Mark Byers. Below function will also adds empty directories if you have them. Examples should make it more clear what is the path added to the zip.
Above is a simple function that should work for simple cases. You can find more elegant class in my Gist:
https://gist.github.com/Eccenux/17526123107ca0ac28e6
我有另一个代码示例可能会有所帮助,使用 python3、pathlib 和 zipfile。
它应该可以在任何操作系统中工作。
I have another code example that may help, using python3, pathlib and zipfile.
It should work in any OS.
如果您想要像任何常见图形文件管理器的压缩文件夹一样的功能,您可以使用以下代码,它使用 zipfile 模块。使用此代码,您将获得以路径作为根文件夹的 zip 文件。
If you want a functionality like the compress folder of any common graphical file manager you can use the following code, it uses the zipfile module. Using this code you will have the zip file with the path as its root folder.
这里有很多答案,我希望我可以贡献自己的版本,它基于原始答案(顺便说一下),但具有更图形化的视角,还为每个
zipfile
设置使用上下文并对 os.walk() 进行排序,以获得有序的输出。有了这些文件夹和文件(以及其他文件夹),我想为每个
cap_
文件夹创建一个.zip
:这是我应用的内容,其中包含注释,以便更好地理解过程。
基本上,对于 os.walk(path) 的每次迭代,我都会打开一个用于
zipfile
设置的上下文,然后迭代files
,它是root
目录中的文件的list
,根据当前root
目录形成每个文件的相对路径,附加到 < code>zipfile 正在运行的上下文。输出如下所示:
要查看每个
.zip
目录的内容,可以使用less
命令:So many answers here, and I hope I might contribute with my own version, which is based on the original answer (by the way), but with a more graphical perspective, also using context for each
zipfile
setup and sortingos.walk()
, in order to have a ordered output.Having these folders and them files (among other folders), I wanted to create a
.zip
for eachcap_
folder:Here's what I applied, with comments for better understanding of the process.
Basically, for each iteration over
os.walk(path)
, I'm opening a context forzipfile
setup and afterwards, iterating iterating overfiles
, which is alist
of files fromroot
directory, forming the relative path for each file based on the currentroot
directory, appending to thezipfile
context which is running.And the output is presented like this:
To see the contents of each
.zip
directory, you can useless
command:使用
pathlib.Path
的解决方案,它独立于所使用的操作系统:A solution using
pathlib.Path
, which is independent of the OS used:为了提供更大的灵活性,例如按名称选择目录/文件,请使用:
对于文件树:
您可以例如仅选择
dir4
和root.txt
:或者仅选择
listdir
在脚本调用目录中并从那里添加所有内容:To give more flexibility, e.g. select directory/file by name use:
For a file tree:
You can e.g. select only
dir4
androot.txt
:Or just
listdir
in script invocation directory and add everything from there:使用
shutil
时请注意,您应该在base_name
arg 中包含输出目录路径:While using
shutil
note that you should include output directory path inbase_name
arg:您可能想查看 zipfile 模块;有文档 http://docs.python.org/library/zipfile.html 。
您可能还需要 os.walk() 来索引目录结构。
You probably want to look at the
zipfile
module; there's documentation at http://docs.python.org/library/zipfile.html.You may also want
os.walk()
to index the directory structure.这是 Nux 给出的答案的一个变体,对我有用:
Here is a variation on the answer given by Nux that works for me:
尝试下面的方法。它对我有用。
Try the below one .it worked for me.
假设您要压缩当前目录中的所有文件夹(子目录)。
Say you want to Zip all the folders(sub directories) in the current directory.
压缩文件或树(目录及其子目录)。
要附加到现有存档,请传递
mode='a'
,以创建新的存档mode='w'
(上面的默认值)。假设您想将 3 个不同的目录树捆绑在同一个存档下。Zip a file or a tree (a directory and its sub-directories).
To append to an existing archive, pass
mode='a'
, to create a fresh archivemode='w'
(the default in the above). So let's say you want to bundle 3 different directory trees under the same archive.显而易见的方法是使用 Shutil,就像第二个最佳答案所说的那样,但是如果您出于某种原因仍然希望使用 ZipFile,并且如果您在这样做时遇到一些麻烦(例如 Windows 中的 ERR 13 等) ,您可以使用此修复:
此修复会递归地迭代给定文件夹中的每个子文件夹/文件,并将它们写入 zip 文件,而不是尝试直接压缩文件夹。
The obvious way to go would be to go with shutil, Like the second top answer says so, But if you still wish to go with ZipFile for some reason, And if you are getting some trouble doing that (Like ERR 13 in Windows etc), You can use this fix:
This one recursively iterates through every sub-folder/file in your given folder, And writes them to a zip file instead of attempting to directly zip a folder.
之前的答案完全忽略了一件事情,即当您在 Windows 上运行代码时,使用 os.path.join() 可以轻松返回 POSIX 不兼容的路径。当使用 Linux 上的任何常见存档软件处理生成的存档时,生成的存档将包含名称中带有文字反斜杠的文件,这不是您想要的。请使用
path.as_posix()
作为arcname
参数!One thing completely missed by previous answers is the fact that using
os.path.join()
can easily return POSIX-incompatible paths when you run the code on Windows. The resulting archive will contain files with literal backslashes in their names when processing it with any common archive software on Linux, which is not what you want. Usepath.as_posix()
for thearcname
parameter instead!这是一种使用 pathlib 和上下文管理器的现代方法。将文件直接放入 zip 中,而不是放入子文件夹中。
Here's a modern approach, using pathlib, and a context manager. Puts the files directly in the zip, rather than in a subfolder.
我通过将 Mark Byers 的解决方案与 Reimund 和 Morten Zilmer 的评论(相对路径并包括空目录)合并来准备一个函数。作为最佳实践,
with
用于 ZipFile 的文件构造。该函数还准备一个默认的 zip 文件名,其中包含压缩目录名称和“.zip”扩展名。因此,它仅适用于一个参数:要压缩的源目录。
I prepared a function by consolidating Mark Byers' solution with Reimund and Morten Zilmer's comments (relative path and including empty directories). As a best practice,
with
is used in ZipFile's file construction.The function also prepares a default zip file name with the zipped directory name and '.zip' extension. Therefore, it works with only one argument: the source directory to be zipped.
嗯,在阅读了这些建议后,我想出了一种非常类似的方法,可以在 2.7.x 上使用,而无需创建“有趣的”目录名称(绝对类似的名称),并且只会在 zip 中创建指定的文件夹。
或者以防万一您需要 zip 中包含一个包含所选目录内容的文件夹。
Well, after reading the suggestions I came up with a very similar way that works with 2.7.x without creating "funny" directory names (absolute-like names), and will only create the specified folder inside the zip.
Or just in case you needed your zip to contain a folder inside with the contents of the selected directory.
创建 zip 文件的函数。
Function to create zip file.
总结其他,做一个函数:
调用:
输出:
最新代码: crifanLib/crifanFile.py
summary others, make a function:
call:
output:
latest code: crifanLib/crifanFile.py