2009-02-04 71 views
30

我想出来从zipfile中删除文件的唯一方法是创建一个临时zipfile,但不删除该文件,然后将其重命名为原始文件名。使用ZipFile模块从zipfile中删除文件

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

这个file_offset在python 2.6中是缺失的,那么是否有另一个选择,通过解压每个文件然后重新压缩它来创建另一个zip文件?

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

+0

我发现Python的bug跟踪讨论从一个zip文件中删除文件的难点该线程:HTTPS://bugs.python。 org/issue6818 – 2016-12-09 21:26:45

回答

34

下面的片段为我工作(从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字节”的错误。 This可能会帮助您了解如何修改主标题。

+0

谢谢,但如果我没有错 - 当你看看zipfile.writestr你会看到这只是一个重新压缩。只需复制已压缩的文件而不解压并再压缩它们会更快。 – RSabet 2009-02-05 19:07:15

+0

@RSabt我同意mdm,解压缩和重新压缩是迄今唯一可行的选择。顺便说一句,想指出mdm的代码有帮助,但是当你要更认真地做某事时,更好的使用os.path.splitext()。 – RayLuo 2013-03-20 08:18:54

0

例程delete_from_zip_file fromruamel.std.zipfile¹允许您根据ZIP中的完整路径或基于(re)模式删除文件。例如。你可以从test.zip使用

from ruamel.std.zipfile import delete_from_zip_file 

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

删除所有.exe文件(请注意*前点)。

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


¹声明:我是该包的作者。

2

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

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)