有没有办法可以使用目录的绝对路径来过滤目录?
shutil.copytree(directory,
target_dir,
ignore = shutil.ignore_patterns("/Full/Path/To/aDir/Common"))
当尝试过滤位于“
aDir
”下的“公共”目录时,这似乎不起作用。如果我这样做:
shutil.copytree(directory,
target_dir,
ignore = shutil.ignore_patterns("Common"))
它可以工作,但是每个名为 Common 的目录都会在该“树”中被过滤,这不是我想要的。
有什么建议吗?
谢谢。
您可以制作自己的忽略功能:
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'))
来自文档:
如果给出了ignore,它必须是一个可调用的,将作为其接收 参数是 copytree() 正在访问的目录及其列表 内容,由 os.listdir() 返回。由于调用了 copytree() 递归地,忽略可调用函数将为每个调用一次 复制的目录。可调用对象必须返回一个序列 相对于当前目录的目录和文件名(即 第二个参数中的项目子集);这些名字将是 在复制过程中被忽略。 ignore_patterns() 可用于创建 这样的可调用函数会忽略基于全局样式模式的名称。
shutil.ignore_patterns() 的 API 不支持绝对路径,但推出自己的变体非常容易。
作为起点,请查看 *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() 中的忽略参数。
或者,不要按原样使用 shutil。源代码短小精悍,因此剪切、粘贴和自定义并不难。
您需要创建自己的忽略函数,该函数检查正在处理的当前目录,并仅当目录为“/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)
非常感谢您的回答。它帮助我设计了自己的
ignore_patterns()
函数来满足一些不同的需求。将代码粘贴到此处,可能会对某人有所帮助。
下面是
ignore_patterns()
函数,用于使用绝对路径排除多个文件/目录。
myExclusionList
--> 包含复制时要排除的文件/目录的列表。该列表可以包含通配符模式。列表中的路径是相对于提供的 srcpath
的。例如:
[排除清单]
java/app/src/main/webapp/WEB-INF/lib/test
unittests
python-buildreqs/apps/abc.tar.gz
3rd-party/jdk*
代码粘贴在下面
def copydir(srcpath, dstpath, myExclusionList, log):
patternlist = []
try:
# Forming the absolute path of files/directories to be excluded
for pattern in myExclusionList:
tmpsrcpath = join(srcpath, pattern)
patternlist.extend(glob.glob(tmpsrcpath)) # myExclusionList can contain wildcard pattern hence glob is used
copytree(srcpath, dstpath, ignore=ignore_patterns_override(*patternlist))
except (IOError, os.error) as why:
log.warning("Unable to copy %s to %s because %s", srcpath, dstpath, str(why))
# catch the Error from the recursive copytree so that we can
# continue with other files
except Error as err:
log.warning("Unable to copy %s to %s because %s", srcpath, dstpath, str(err))
# [START: Ignore Patterns]
# Modified Function to ignore patterns while copying.
# Default Python Implementation does not exclude absolute path
# given for files/directories
def ignore_patterns_override(*patterns):
"""Function that can be used as copytree() ignore parameter.
Patterns is a sequence of glob-style patterns
that are used to exclude files/directories"""
def _ignore_patterns(path, names):
ignored_names = []
for f in names:
for pattern in patterns:
if os.path.abspath(join(path, f)) == pattern:
ignored_names.append(f)
return set(ignored_names)
return _ignore_patterns
# [END: Ignore Patterns]
平台无关。路径全局模式 [".gitkeep","app/build","*.txt"]
def callbackIgnore(paths):
""" callback for shutil.copytree """
def ignoref(directory, contents):
arr = []
for f in contents:
for p in paths:
if (pathlib.PurePath(directory, f).match(p)):
arr.append(f)
return arr
return ignoref