Фильтровать каталог при использовании shutil.copytree? - PullRequest
10 голосов
/ 21 октября 2011

Есть ли способ отфильтровать каталог, используя абсолютный путь к нему?

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 будет отфильтрован в этом "дереве", а это не то, что я хочу.

Есть предложения?

Спасибо.

Ответы [ 3 ]

13 голосов
/ 21 октября 2011

Вы можете сделать свою собственную функцию игнорирования:

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'))

Из документов:

Если задано игнорирование, это должен быть вызываемый объект, который получит в качестве своего аргументы каталог, который посещает copytree (), и список его содержимое, возвращаемое os.listdir (). Так как copytree () вызывается рекурсивно, вызываемое игнорирование будет вызываться один раз для каждого каталог, который копируется. Вызываемый должен возвращать последовательность имена каталогов и файлов относительно текущего каталога (т.е. подмножество элементов во втором аргументе); эти имена будут тогда игнорируется в процессе копирования. ignore_patterns () может быть использован для создания такой вызываемый, что игнорирует имена, основанные на шаблонах в стиле глобуса.

4 голосов
/ 21 октября 2011

API для 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 () .

В качестве альтернативы, не используйте shutil как есть. Исходный код короткий и приятный, поэтому его нетрудно вырезать, вставить и настроить.

3 голосов
/ 21 октября 2011

Вы захотите создать свою собственную функцию игнорирования, которая проверяет текущий обрабатываемый каталог и возвращает список, содержащий «Common», только если dir равен «/Full/Path/To/aDir'.

* 1002»*
...