使用python解压缩目录结构

Fly*_*er1 29 python unzip

我有一个zip文件,其中包含以下目录结构:

dir1\dir2\dir3a
dir1\dir2\dir3b
Run Code Online (Sandbox Code Playgroud)

我正在尝试解压缩它并维护目录结构但是我收到错误:

IOError: [Errno 2] No such file or directory: 'C:\\\projects\\\testFolder\\\subdir\\\unzip.exe'
Run Code Online (Sandbox Code Playgroud)

其中testFolder是dir1,而subdir是dir2.

是否有快速解压缩文件和维护目录结构的方法?

Jef*_*eff 23

如果你使用的是Python 2.6,那么extract和extractall方法都很棒.我现在必须使用Python 2.5,所以我只需要创建目录,如果它们不存在.您可以使用该namelist()方法获取目录列表.目录将始终以正斜杠结束(即使在Windows上),例如,

import os, zipfile

z = zipfile.ZipFile('myfile.zip')
for f in z.namelist():
    if f.endswith('/'):
        os.makedirs(f)
Run Code Online (Sandbox Code Playgroud)

你可能不希望完全这样做(也就是说,当你迭代名单时,你可能想要提取zip文件的内容),但是你明白了.

  • 可能想在try中包装`os.makedirs(f)`:除了(OSError,WindowsError):阻止以防文件夹已经存在. (3认同)

bob*_*nce 16

不要信任extract()或extractall().

这些方法盲目地将文件提取到文件名中给出的路径.但ZIP文件名可以是任何东西,包括危险的字符串,如"x /../../../ etc/passwd".提取此类文件,您可能刚刚破坏了整个服务器.

也许这应该被认为是Python的zipfile模块中的一个可报告的安全漏洞,但是过去任何数量的zip-dearchivers都表现出完全相同的行为.要安全地取消归档具有文件夹结构的ZIP文件,您需要深入检查每个文件路径.

  • 看起来自2.7.4以来它已经改变:http://docs.python.org/2/library/zipfile#zipfile.ZipFile.extractall"zipfile模块试图阻止它." (2认同)

DNS*_*DNS 8

我试过了,可以重现它.该extractall方法,如其他答案建议,并没有解决问题.这看起来像zipfile模块中的一个错误(也许仅限于Windows?),除非我误解了zipfiles的结构.

testa\
testa\testb\
testa\testb\test.log
> test.zip

>>> from zipfile import ZipFile
>>> zipTest = ZipFile("C:\\...\\test.zip")
>>> zipTest.extractall("C:\\...\\")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\zipfile.py", line 940, in extractall
  File "...\zipfile.py", line 928, in extract
  File "...\zipfile.py", line 965, in _extract_member
IOError: [Errno 2] No such file or directory: 'C:\\...\\testa\\testb\\test.log'
Run Code Online (Sandbox Code Playgroud)

如果我这样做printdir(),我会得到这个(第一栏):

>>> zipTest.printdir()
File Name
testa/testb/
testa/testb/test.log
Run Code Online (Sandbox Code Playgroud)

如果我尝试仅提取第一个条目,如下所示:

>>> zipTest.extract("testa/testb/")
'C:\\...\\testa\\testb'
Run Code Online (Sandbox Code Playgroud)

在磁盘上,这会导致创建一个文件夹testa,里面有一个文件 testb.这显然是后续尝试提取test.log失败的原因; testa\testb是文件,而不是文件夹.

编辑#1:如果只提取文件,那么它可以工作:

>>> zipTest.extract("testa/testb/test.log")
'C:\\...\\testa\\testb\\test.log'
Run Code Online (Sandbox Code Playgroud)

编辑#2:杰夫的代码是要走的路; 迭代namelist; 如果是目录,请创建目录.否则,解压缩文件.


小智 6

我知道说这可能有点晚,但杰夫是对的.它很简单:

import os
from zipfile import ZipFile as zip

def extractAll(zipName):
    z = zip(zipName)
    for f in z.namelist():
        if f.endswith('/'):
            os.makedirs(f)
        else:
            z.extract(f)

if __name__ == '__main__':
    zipList = ['one.zip', 'two.zip', 'three.zip']
    for zip in zipList:
        extractAll(zipName)
Run Code Online (Sandbox Code Playgroud)

  • 好像`zipfile.ZipFile(zip_name).extractall()`就是这么做的. (4认同)