Фильтровать каталог при использовании 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 будет отфильтрован в этом "дереве", а это не то, что мне нужно.
Какие-либо предложения?
Благодарю.
5 ответов
Вы можете сделать свою собственную функцию игнорирования:
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() может использоваться для создания такого вызываемого объекта, который игнорирует имена на основе шаблонов в стиле glob.
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
Вы можете видеть, что он возвращает функцию, которая принимает путь и список имен, и возвращает набор имен, которые следует игнорировать. Чтобы поддержать ваш вариант использования, создайте собственную подобную функцию, которая использует аргумент пути. Передайте вашу функцию параметру ignore в вызове copytree ().
В качестве альтернативы, не используйте shutil как есть. Исходный код короткий и приятный, поэтому его нетрудно вырезать, вставить и настроить.
Вы захотите создать свою собственную функцию игнорирования, которая проверяет текущий обрабатываемый каталог и возвращает список, содержащий "Common", только если dir равен "/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)
Большое спасибо за ответ. Это помогло мне разработать мою собственную функцию для немного других требований. Вставка кода здесь может кому-то помочь.
Ниже
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