使用单个文件名过滤tarfile.add

时间:2017-10-13 16:51:04

标签: python tarfile

使用filter添加目录时,有没有办法访问tarfile.add lambda中的各个文件名?

我正在使用tarfile模块来创建项目目录的存档。我不再需要这些文件中的一些,我想忽略:

myproj/  # example; actual project directory structure much deeper
    importantfile.txt
    semi-importantfile.doc
    useless-file.exe  # ignore this one

我现在正在做的是使用tarfile.add的{​​{1}}参数跳过exclude

useless-file.exe

我知道import tarfile with tarfile.open('mytar.tar', 'w') as mytar: mytar.add('myproj', exclude=lambda x: os.path.basename(x) == 'useless-file.exe') 现已弃用,为了防范未来,我正在尝试切换到使用新的exclude参数。

filter

然而,这样做最终会将 mytar.add('myproj', filter=lambda x: ( x if x.name != 'useless-file.exe' else None)) 添加到tarball中。通过一些测试,我发现这是因为,虽然useless-file.exe以递归方式提供了目录的名称及其所有内容,但exclude仅获取明确添加的文件的filter(在此case,目录TarInfo

那么有没有办法使用myproj复制exclude的行为?如果可能的话,我宁愿不以递归方式遍历所有目录,只是为了检查我是否添加了任何不需要的文件。

解决方案说明

有关问题的完整说明,请参阅@ larsks的答案。我的问题是在filter使用exclude os.path.basename时调用了x(请参阅上面编辑的代码),但在使用x.name时我忘记在filter上执行此操作。

1 个答案:

答案 0 :(得分:1)

我不认为for方法的行为与您认为的方式相同。例如,如果我的目录结构如下:

filter

我运行以下代码:

example/
  file0.1
  file0.2
  dir1/
    file1.1
    file1.2

我看作输出:

import tarfile

def myfilter(thing):
    print('myfilter called for {thing.name}'.format(thing=thing))
    return thing

t = tarfile.open('archive.tar', mode='w')
t.add('example', recursive=True, filter=myfilter)

也就是说,每个添加到存档的项目都会调用一次过滤器。如果想要排除myfilter called for example myfilter called for example/file0.1 myfilter called for example/file0.2 myfilter called for example/dir1 myfilter called for example/dir1/file1.1 myfilter called for example/dir1/file1.2 ,我会写一个看起来像这样的过滤函数:

example/dir1/file1.1

在上例中使用此作为过滤器时,生成的存档包含:

def exclude_file1(thing):
    if thing.name != 'example/dir1/file1.1':
        return thing

编辑:上面的示例是使用Python 3.5测试的)