0

在 Windows 上的 Python 2.7.4 中,如果我的目录结构如下:

test/foo/a.bak
test/foo/b.bak
test/foo/bar/c.bak
test/d.bak

我使用以下内容将它们添加到现有存档中,以使“d.bak”位于存档的根目录:

import zipfile
import os.path
import fnmatch

def find_files(directory, pattern):
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if fnmatch.fnmatch(basename, pattern):
                filename = os.path.join(root, basename)
                yield filename

if __name__=='__main__':
    z = zipfile.ZipFile("testarch.zip", "a", zipfile.ZIP_DEFLATED)

    for filename in find_files('test', '*.*'):
        print 'Found file:', filename
        z.write(filename, os.path.basename(filename), zipfile.ZIP_DEFLATED)

    z.close()

zip 文件的目录是平面的。当其中存在子目录时才会创建foo/目录(如果我 exclude ,它不会创建目录。如果包含,则创建但如果有意义则不创建),但没有子目录或文件:test/foo/bar/c.bakfoo/foo/bar/

foo/
a.bak
b.bak
c.bak
d.bak

我错过了什么吗?

4

2 回答 2

2

问题是您明确要求它展平所有路径:

z.write(filename, os.path.basename(filename), zipfile.ZIP_DEFLATED)

如果您查看文档,则默认arcname值为:

与 相同filename,但没有驱动器号并删除了前导路径分隔符

但是你用os.path.basename(filename). (如果您不知道做什么basename,它会返回“最后一个路径名组件”。如果您不想要最后一个路径名组件,请不要调用basename。)

如果您这样做z.write('test/foo/bar/c.bak'),它将创建一个名为 zip 的条目test/foo/bar/c.bak,但如果您这样做z.write('test/foo/bar/c.bak', 'c.bak'),它将创建一个名为 .zip 的 zip 条目c.bak。由于您对所有条目都这样做,因此整个事情最终都变平了。

于 2013-04-09T00:50:14.863 回答
0

我想到了。正如abarnet指出的那样,我误读了 zipfiles 上的文档。使用以下函数,我可以为 zip 文件创建正确的存档名称:

def createArchName(path):
    line = path
    if "\\" in line:
        ''' windows '''
        discard, val = line.split("\\", 1)
        return val
    else:
        ''' unix '''
        discard, val = line.split("/", 1)
        return val

对于有兴趣的人,完整的代码如下:

import urllib2
import zipfile
import os.path
import fnmatch

def find_files(directory, pattern):
    for root, dirs, files in os.walk(directory):
        for basename in files:
            if fnmatch.fnmatch(basename, pattern):
                filename = os.path.join(root, basename)
                yield filename

def createArchName(path):
    line = path
    if "\\" in line:
        ''' windows '''
        discard, val = line.split("\\", 1)
        return val
    else:
        ''' unix '''
        discard, val = line.split("/", 1)
        return val


if __name__=='__main__':
    if not os.path.exists("test"):
        os.mkdir("test")

    z = zipfile.ZipFile("testarch.zip", "a", zipfile.ZIP_DEFLATED)

    for filename in find_files('test', '*.*'):
        archname = createArchName(filename)
        print 'Found file:', archname
        z.write(filename, archname, zipfile.ZIP_DEFLATED)

    z.close()
于 2013-04-09T01:40:21.313 回答