#python #shutil #copytree
#python #shutil #copytree
Вопрос:
Есть ли способ отфильтровать каталог, используя абсолютный путь к нему?
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 будет отфильтрован в этом «дереве», чего я не хочу.
Есть предложения?
Спасибо.
Ответ №1:
Вы можете создать свою собственную функцию игнорирования:
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() можно использовать для создания такого вызываемого объекта, который игнорирует имена на основе шаблонов в стиле глобуса.
Комментарии:
1. Небольшая поправка, функция ignoref должна возвращать список (т.е. [f для f в …] вместо генератора.
Ответ №2:
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. Передайте свою функцию параметру ignore при вызове copytree() .
В качестве альтернативы, не используйте shutil как есть. Исходный код короткий и приятный, поэтому его нетрудно вырезать, вставлять и настраивать.
Ответ №3:
Вы захотите создать свою собственную функцию игнорирования, которая проверяет текущий обрабатываемый каталог и возвращает список, содержащий ‘Common’, только если каталог ‘/ Full / Path /To / aDir’.
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:
Большое спасибо за ответ. Это помогло мне разработать собственную 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]
Ответ №5:
Не зависит от платформы. Пути к шаблонам глобуса [«.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