python - 使用 zipfile 归档目录内容,同时从列表中跳过文件
问题描述
我正在使用zipfile
创建目录中所有文件的存档(递归地,同时保留包括空文件夹在内的目录结构)并希望该过程跳过列表中指定的文件名。
这是 os.walk 遍历目录并将所有包含文件和目录添加到存档的基本功能。
def zip_dir(path):
zipname = str(path.rsplit('/')[-1]) + '.zip'
with zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) as zf:
if os.path.isdir(path):
for root, dirs, files in os.walk(path):
for file_or_dir in files + dirs:
zf.write(os.path.join(root, file_or_dir),
os.path.relpath(os.path.join(root, file_or_dir),
os.path.join(path, os.path.pardir)))
elif os.path.isfile(filepath):
zf.write(os.path.basename(filepath))
zf.printdir()
zf.close()
我们可以看到代码也应该有处理单个文件的能力,但它主要是我们感兴趣的目录部分。
现在假设我们有一个文件名列表,我们希望将其排除在添加到 zip 存档中。
skiplist = ['.DS_Store', 'tempfile.tmp']
实现这一目标的最佳和最干净的方法是什么?
我尝试使用zip
which 有点成功,但由于某种原因导致它排除空文件夹(应该包括空文件夹)。我不确定为什么会这样。
skiplist = ['.DS_Store', 'tempfile.tmp']
for root, dirs, files in os.walk(path):
for (file_or_dir, skipname) in zip(files + dirs, skiplist):
if skipname not in file_or_dir:
zf.write(os.path.join(root, file_or_dir),
os.path.relpath(os.path.join(root, file_or_dir),
os.path.join(path, os.path.pardir)))
看看是否有人有一个聪明的想法来添加跳过特定文件扩展名的能力也会很有趣,也许像.endswith('.png')
但我不完全确定如何将它与现有的跳过列表合并在一起。
我还将感谢有关该功能的任何其他一般性评论,以及它是否确实按预期工作而没有意外,以及任何优化或改进的建议。
解决方案
您可以简单地检查文件是否不在skiplist
:
skiplist = {'.DS_Store', 'tempfile.tmp'}
for root, dirs, files in os.walk(path):
for file in files + dirs:
if file not in skiplist:
zf.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, os.path.pardir)))
这将确保skiplist
不会将其中的文件添加到存档中。
另一个优化是创建skiplist
一个集合,以防万一它变得非常大,并且您希望使用列表进行恒定时间 O(1) 查找而不是线性 O(N) 查找。
您可以在TimeComplexity进行更多研究,它显示了数据结构上各种 Python 操作的时间复杂度。
至于扩展,你可以使用os.path.splitext()
提取扩展并使用与上面相同的逻辑:
from os.path import splitext
extensions = {'.png', '.txt'}
for root, dirs, files in os.walk(path):
for file in files:
_, extension = splitext(file)
if extension not in extensions:
zf.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, os.path.pardir)))
如果你想结合以上特性,那么你可以分别处理文件和目录的逻辑:
from os.path import splitext
extensions = {'.png', '.txt'}
skiplist = {'.DS_Store', 'tempfile.tmp'}
for root, dirs, files in os.walk(path):
for file in files:
_, extension = splitext(file)
if file not in skiplist and extension not in extensions:
zf.write(os.path.join(root, file),
os.path.relpath(os.path.join(root, file),
os.path.join(path, os.path.pardir)))
for directory in dirs:
if directory not in skiplist:
zf.write(os.path.join(root, directory),
os.path.relpath(os.path.join(root, directory),
os.path.join(path, os.path.pardir)))
注意:上面的代码片段不能单独工作,你需要编织你当前的代码来使用这些想法。
推荐阅读
- python - 带有非英文符号的 Django sql 语句
- python - 无法在 jupyter 上安装/运行熊猫,出现错误“熊猫”没有属性
- python - 如何从 Python 中的给定节点列表创建简单的非二叉树
- powershell - 比较 2 个文件夹并将差异复制到另一个文件夹中 - 我的代码缺少一些东西
- java - 如何通过 TDLib 从 Telegram 获取频道的数据列表?
- javascript - Vue:当我更改控制台日志时,数据仅在第一次渲染时传递给孩子,在刷新时被删除
- java - Websphere 超时异常
- php - 用购物车总数和订阅期替换 WooCommerce“下订单”按钮文本
- docker - docker run 和 docker-compose 结果不同?
- html - 为什么我不能根据 CSS 中的文本调整图像大小?