14

有没有办法通过使用目录的绝对路径来过滤目录?

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 的目录都将在那个“树”中过滤,这不是我想要的。

有什么建议么 ?

谢谢。

4

4 回答 4

16

您可以制作自己的忽略功能:

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.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() 可用于创建这样的可调用对象,该可调用对象忽略基于 glob 样式模式的名称。

于 2011-10-20T21:01:46.227 回答
4

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

您可以看到它返回一个接受路径和名称列表的函数,并返回一组要忽略的名称。为了支持您的用例,请创建您自己的使用路径参数的类似函数。将您的函数传递给对copytree()的调用中的忽略参数。

或者,不要按原样使用shutil。源代码短小精悍,因此不难剪切、粘贴和自定义。

于 2011-10-20T21:03:30.907 回答
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)
于 2011-10-20T21:07:37.557 回答
0

非常感谢您的回答。它帮助我设计了自己的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]
于 2021-02-18T17:10:33.343 回答