繁体   English   中英

使用 ZipFile 模块从 zipfile 中删除文件

[英]Delete file from zipfile with the ZipFile Module

我想出的从 zip 文件中删除文件的唯一方法是创建一个没有要删除的文件的临时 zip 文件,然后将其重命名为原始文件名。

在 python 2.4 中, ZipInfo 类有一个属性file_offset ,因此可以创建第二个 zip 文件并将数据复制到其他文件而无需解压缩/重新压缩。

python 2.6 中缺少此file_offset ,那么除了通过解压缩每个文件然后再次重新压缩来创建另一个 zipfile 之外还有其他选择吗?

是否有直接删除 zip 文件中文件的方法,我搜索过但没有找到任何东西。

以下代码段对我有用(从Zip存档中删除所有* .exe文件):

zin = zipfile.ZipFile ('archive.zip', 'r')
zout = zipfile.ZipFile ('archve_new.zip', 'w')
for item in zin.infolist():
    buffer = zin.read(item.filename)
    if (item.filename[-4:] != '.exe'):
        zout.writestr(item, buffer)
zout.close()
zin.close()

如果您将所有内容都读到内存中,则可以省去第二个文件。 但是,此片段重新压缩了所有内容。

仔细检查后, ZipInfo.header_offset是文件开始的偏移量。 该名称具有误导性,但主要的Zip标头实际上存储在文件末尾。 我的十六进制编辑器确认了这一点。

因此,您将遇到以下问题:您还需要删除主标头中的目录条目,否则它将指向一个不再存在的文件。 如果您也要保留要删除的文件的本地标头,则可以保留主标头的完整性,但是我不确定。 您是如何使用旧模块执行此操作的?

如果不修改主标头,则在打开它时会出现错误“ zipfile中缺少X字节”。 可能有助于您了解如何修改主标头。

不是很优雅,但这是我做到的:

import subprocess
import zipfile

z = zipfile.ZipFile(zip_filename)

files_to_del = filter( lambda f: f.endswith('exe'), z.namelist()]

cmd=['zip', '-d', zip_filename] + files_to_del
subprocess.check_call(cmd)

# reload the modified archive
z = zipfile.ZipFile(zip_filename)

基于Elias Zamaria对问题的评论。

通读Python-Issue #51067后,我想提供有关它的更新。

今天,解决方案已经存在,但由于缺少作者的贡献者协议,它未被 Python 批准。

不过,您可以从https://github.com/python/cpython/blob/659eb048cc9cac73c46349eb29845bc5cd630f09/Lib/zipfile.py获取代码并从中创建一个单独的文件。 之后只需从您的项目而不是内置的 python 库中引用它: import myproject.zipfile as zipfile

用法:

with zipfile.ZipFile(f"archive.zip", "a") as z:
    z.remove(f"firstfile.txt")

我相信它将包含在未来的 python 版本中。 对我来说,它就像给定用例的魅力一样。

常规delete_from_zip_fileruamel.std.zipfile ¹允许你删除基于它的完整路径上的文件的ZIP内,或基于( re )模式。 例如,您可以使用以下方法从test.zip删除所有.exe文件:

from ruamel.std.zipfile import delete_from_zip_file

delete_from_zip_file('test.zip', pattern='.*.exe')  

(请注意*之前的点)。

这与mdm的解决方案(包括需要重新压缩)相似,但是会在内存中重新创建ZIP文件(使用InMemZipFile()类),并在完全读取旧文件后将其覆盖。


¹ 免责声明:我是该软件包的作者。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM