Обратный вызов Ignore для python shutil.copytree() не принимает полный путь

Я хотел бы указать полные пути к игнорируемым файлам и каталогам при вызове shutil.copytree(). Что-то вроде

def my_ignore(dir, files):

    # return ["exclude.file"] # working

    return ["/full_path_to/exclude.file"] # Not working

shutil.copytree(src, dest, ignore=my_ignore)

После этого исключенный файл все еще там, если я не верну просто имя файла вместо полного пути. Дело в том, что я действительно хочу настроить конкретный файл вместо всех совпадающих имен файлов в разных каталогах.

Я упомянул ряд вопросов, таких как: Как написать функцию обратного вызова для игнорирования в shutil.copytree

Фильтровать каталог при использовании shutil.copytree?

Но ни один из ответов не работает. Похоже, что ловушка игнорирования может возвращать только глобальный стиль, и любой созданный полный путь не будет работать.

Я что-то пропустил?

2 ответа

Решение

ignore действительно должен возвращать только имена файлов, которые игнорируются. Тем не менее, функция вызывается для каждого каталога shutil.copytree() посещения; Вы можете игнорировать файлы в каталоге.

Если у вас есть полный путь к файлу, который нужно игнорировать, сопоставьте его с первым параметром, переданным вашему ignore функция; это полный путь к этому каталогу:

def my_ignore(dir, files):
    if dir == '/full_path_to':
        return {"exclude.file"}

Я возвращаю набор здесь; установить членство тестирования быстрее, чем со списком.

Если у вас есть предопределенный набор путей, которые нужно игнорировать, проанализируйте их в словаре; ключи - это путь к каталогу, значения наборов имен файлов в этом пути:

from collections import defaultdict

to_ignore = defaultdict(set)
for path in ignored_paths:
    dirname, filename = os.path.split(path)
    to_ignore[dirname].add(filename)

def my_ignore(src, files):
    return to_ignore.get(src, set())

Это не волшебство. copytree() копирует содержимое одного каталога за раз, и он специально ищет имена файлов в списке игнорирования, который вы возвращаете. Полный путь никогда не является именем файла, поэтому он никогда не совпадает.

Тем не менее dir Параметр поможет вам сделать то, что вы хотите:

def my_ignore(dir, files):
    if dir == "/full/path/to":
        return ["exclude.file"]
    else:
        return []
Другие вопросы по тегам