如何在更改名称时使用 python zipfile 库提取文件

How do I extract a file with the python zipfile library while changing it's name

这是由路径文件问题引起的(不幸的是 this 在我的情况下似乎不是这样)。

我有一个 zip 文件,我想用 python 解压它。压缩文件似乎是在 windows 上创建的。我必须从压缩文件中提取文件的代码是这样的:

def unzip_file(zipfile_path):
    z = zipfile.ZipFile(zipfile_path)
    # get pathname without extension
    directory = os.path.splitext(zipfile_path)[0]
    print directory
    if not os.path.exists(directory):
        os.makedirs(directory)
    #this line doesn't work. tries to extract "Foobar\baz.quux" to directory and complains that the directory doesn't exist
    # z.extractall(directory)
    for name in z.namelist():
        # actual dirname we want is this
        # (dirname, filename) = os.path.split(name)
        # I've tried to be cross-platform, (see above) but aparently zipfiles save filenames as
        # Foobar\filename.log so I need this for cygwin
        dir_and_filename = name.split('\')
        if len(dir_and_filename) >1:
            dirname = dir_and_filename[0:-1]
            filename = dir_and_filename[-1]
        else:
            dirname = ['']
            filename = dir_and_filename[0]

        out_dir = os.path.join(directory, *dirname)
        print "Decompressing " + name + " on " + out_dir
        if not os.path.exists(out_dir):
            os.makedirs(out_dir)
        z.extract(name, out_dir)
    return directory

虽然这看起来过于复杂,但这是为了尝试解决我发现的一些错误。压缩文件的一个成员是 Foobar\filename.log。在尝试提取它时抱怨该目录不存在。我需要一种方法来使用这样的方法:

zipfile.extract_to(member_name, directory_name, file_name_to_write)

其中 member name 是要读取的成员的名称(在此示例中 Foobar\filename.log),directory_name 是我们要写入的目录的名称,file_name_to_write 是我们要写入的文件的名称(在本例中为 filename.log)。这似乎不被支持。有没有人对如何跨平台实现提取这种具有嵌套表达式的 zip 存档有任何其他想法?

根据this answer,我的压缩文件可能不符合压缩文件规范(它说:

All slashes MUST be forward slashes '/' as opposed to backwards slashes '\' for compatibility with Amiga and UNIX file systems etc.

the zipfile specification 4.4.17) 我该如何解决这个问题?

我通过简单地支付 unzip 解决了这个问题。我们需要检查 0 或 1 的退出代码,因为 unzip 命令返回了 1 的退出代码(由于压缩文件格式错误,给出的消息类似于 warning: zipfile appears to contain backslashes as path separators.

#!/bin/bash
unzip  -d 
exit_code=$?
# we catch exit_codes < 2 as the zipfiles are malformed
if [ $exit_code -lt 2 ]
then exit 0
else exit $exit_code
fi