从zip中提取文件而不使用python zipfile保留顶级文件夹

时间:2011-12-31 18:49:45

标签: python zip extract unzip zipfile

我正在使用当前代码从zip文件中提取文件,同时保留目录结构:

zip_file = zipfile.ZipFile('archive.zip', 'r')
zip_file.extractall('/dir/to/extract/files/')
zip_file.close()

以下是示例zip文件的结构:

/dir1/file.jpg
/dir1/file1.jpg
/dir1/file2.jpg

最后我想要这个:

/dir/to/extract/file.jpg
/dir/to/extract/file1.jpg
/dir/to/extract/file2.jpg

但是只有当zip文件包含一个包含所有文件的顶级文件夹时才应该忽略它,所以当我用这种结构提取zip时:

/dir1/file.jpg
/dir1/file1.jpg
/dir1/file2.jpg
/dir2/file.txt
/file.mp3

应该保持这样:

/dir/to/extract/dir1/file.jpg
/dir/to/extract/dir1/file1.jpg
/dir/to/extract/dir1/file2.jpg
/dir/to/extract/dir2/file.txt
/dir/to/extract/file.mp3

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

如果我正确理解你的问题,你想在解压缩之前从zip中删除任何公共前缀目录。

如果是这样,那么以下脚本应该做你想做的事情:

import sys, os
from zipfile import ZipFile

def get_members(zip):
    parts = []
    # get all the path prefixes
    for name in zip.namelist():
        # only check files (not directories)
        if not name.endswith('/'):
            # keep list of path elements (minus filename)
            parts.append(name.split('/')[:-1])
    # now find the common path prefix (if any)
    prefix = os.path.commonprefix(parts)
    if prefix:
        # re-join the path elements
        prefix = '/'.join(prefix) + '/'
    # get the length of the common prefix
    offset = len(prefix)
    # now re-set the filenames
    for zipinfo in zip.infolist():
        name = zipinfo.filename
        # only check files (not directories)
        if len(name) > offset:
            # remove the common prefix
            zipinfo.filename = name[offset:]
            yield zipinfo

args = sys.argv[1:]

if len(args):
    zip = ZipFile(args[0])
    path = args[1] if len(args) > 1 else '.'
    zip.extractall(path, get_members(zip))

答案 1 :(得分:1)

阅读ZipFile.namelist()返回的条目以查看它们是否在同一目录中,然后打开/读取每个条目并将其写入使用open()打开的文件。

答案 2 :(得分:0)

这可能是zip存档本身的问题。在python提示符下,尝试查看文件是否在zip文件本身的正确目录中。

import zipfile

zf = zipfile.ZipFile("my_file.zip",'r')
first_file = zf.filelist[0]
print file_list.filename

这应该说像“dir1” 重复上面的步骤,将1和1的索引替换为文件列表,如此first_file = zf.filelist[1]这次输出应该看起来像'dir1 / file1.jpg'如果不是这样,那么zip文件不包含目录并将被解压缩所有到一个目录。