使用shutil.copytree时如何过滤目录?
有没有办法可以用绝对路径来过滤一个目录呢?
shutil.copytree(directory,
target_dir,
ignore = shutil.ignore_patterns("/Full/Path/To/aDir/Common"))
当我尝试过滤位于“aDir
”下的“Common”目录时,这似乎不起作用。如果我这样做:
shutil.copytree(directory,
target_dir,
ignore = shutil.ignore_patterns("Common"))
这样是可以的,但在那个“树”结构中,所有叫做Common的目录都会被过滤掉,这不是我想要的结果。
有什么建议吗?
谢谢。
5 个回答
3
你需要自己写一个忽略的函数,这个函数会检查当前正在处理的目录,如果这个目录是'/Full/Path/To/aDir',那么就返回一个只包含'Common'的列表。
def ignore_full_path_common(dir, files):
if dir == '/Full/Path/To/aDir':
return ['Common']
return []
shutil.copytree(directory, target_dir, ignore=ignore_full_path_common)
4
shutil.ignore_patterns()这个功能不支持绝对路径,但其实自己写一个类似的功能非常简单。
作为起点,可以看看*ignore_patterns*的源代码:
def ignore_patterns(*patterns):
"""Function that can be used as copytree() ignore parameter.
Patterns is a sequence of glob-style patterns
that are used to exclude files"""
def _ignore_patterns(path, names):
ignored_names = []
for pattern in patterns:
ignored_names.extend(fnmatch.filter(names, pattern))
return set(ignored_names)
return _ignore_patterns
你会发现它返回一个函数,这个函数接受一个路径和一组名称,然后返回一组要忽略的名称。为了满足你的需求,可以创建一个类似的函数,利用path这个参数。然后把你的函数传给copytree()中的ignore参数。
另外,你也可以不直接使用shutil。它的源代码很简短,所以剪切、粘贴并进行自定义并不难。
19
你可以自己写一个忽略的函数:
shutil.copytree('/Full/Path', 'target',
ignore=lambda directory, contents: ['Common'] if directory == '/Full/Path/To/aDir' else [])
或者,如果你想用相对路径来调用 copytree
:
import os.path
def ignorePath(path):
def ignoref(directory, contents):
return (
f for f in contents
if os.path.abspath(os.path.join(directory, f)) == path)
return ignoref
shutil.copytree('Path', 'target', ignore=ignorePath('/Full/Path/To/aDir/Common'))
根据文档说明:
如果提供了忽略功能,它必须是一个可以调用的函数,这个函数会接收两个参数:一个是当前正在被
copytree()
访问的目录,另一个是这个目录下的内容列表,这个列表是通过os.listdir()
得到的。因为copytree()
是递归调用的,所以每复制一个目录,这个忽略函数就会被调用一次。这个函数必须返回一个相对于当前目录的目录和文件名的列表(也就是它第二个参数中的一部分);这些名字在复制过程中会被忽略。你可以使用ignore_patterns()
来创建这样一个函数,它可以根据特定的模式来忽略文件名。