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

时间:2015-02-12 17:40:33

标签: python zip zipfile

这是由路径文件问题引起的(遗憾的是this在我的案例中似乎不是真的。)

我有一个zipfile,我试图用python提取。 zip文件似乎是在Windows上创建的。我必须从zipfile中提取文件的代码如下:

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

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

zipfile.extract_to(member_name, directory_name, file_name_to_write)

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

根据this answer,我所拥有的zipfile可能不符合zipfile规范(它说:

  

所有斜线   必须是正斜杠' /'而不是   向后斜线' \'与Amiga兼容   和UNIX文件系统等。

the zipfile specification中的

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

1 个答案:

答案 0 :(得分:0)

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

#!/bin/bash
unzip $1 -d $2
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