Как с помощью `shutil` выполнить рекурсивное копирование директорий?

Для рекурсивного копирования директорий с помощью `shutil` используется функция `shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False, dirs_exist_ok=False)`. `src` - исходная директория, `dst` - целевая директория.

Для рекурсивного копирования директорий в Python с использованием модуля shutil, применяется функция shutil.copytree().

Функция copytree() принимает как минимум два аргумента:

  • src: Путь к исходной директории, которую необходимо скопировать.
  • dst: Путь к целевой директории, куда будет скопирована исходная директория. Если целевая директория не существует, она будет создана. Если существует, и она пустая, файлы из исходной будут скопированы в нее. Если в целевой директории есть другие файлы/папки, копирование завершится с ошибкой (по умолчанию).

Пример использования:


import shutil
import os

source_dir = '/путь/к/исходной/директории'
destination_dir = '/путь/к/целевой/директории'

try:
    shutil.copytree(source_dir, destination_dir)
    print(f"Директория '{source_dir}' успешно скопирована в '{destination_dir}'")
except FileExistsError:
    print(f"Ошибка: Директория '{destination_dir}' уже существует.")
except shutil.Error as errors:
    print(f"Ошибка при копировании:")
    for error in errors.errors:
        src, dst, msg = error
        print(f"  Не удалось скопировать '{src}' в '{dst}': {msg}")
except Exception as e:
    print(f"Произошла непредвиденная ошибка: {e}")

Важные замечания:

  • Перезапись: По умолчанию, copytree() не будет перезаписывать существующие файлы или директории в целевой директории. Если целевая директория существует и не пуста, возникнет исключение FileExistsError.
  • Игнорирование: Для выборочного копирования (например, исключения определенных файлов или директорий), можно использовать аргумент ignore, который принимает функцию, возвращающую список игнорируемых элементов. Это позволяет гибко настраивать процесс копирования. Аргумент dirs_exist_ok=True, доступный начиная с Python 3.8, позволяет избежать ошибки FileExistsError при существовании целевой директории, объединяя содержимое исходной с целевой.
  • Обработка ошибок: При возникновении ошибок во время копирования (например, недостаточно прав доступа), функция copytree() выбрасывает исключение shutil.Error, которое содержит список кортежей с информацией об ошибках. Необходимо предусмотреть обработку этого исключения для обеспечения стабильной работы программы.
  • Метаданные: По умолчанию, copytree() пытается скопировать метаданные файлов (например, права доступа, время последнего изменения). Это поведение можно контролировать с помощью других аргументов функции.

Пример с обработкой ошибок и игнорированием:


import shutil
import os

def ignore_patterns(patterns):
    def _ignore_patterns(path, names):
        return set(shutil.ignore_patterns(*patterns)(path, names))
    return _ignore_patterns

source_dir = '/путь/к/исходной/директории'
destination_dir = '/путь/к/целевой/директории'

try:
    shutil.copytree(source_dir, destination_dir, ignore=ignore_patterns('*.pyc', 'tmp*'), dirs_exist_ok=True)
    print(f"Директория '{source_dir}' успешно скопирована в '{destination_dir}'")
except shutil.Error as errors:
    print(f"Ошибка при копировании:")
    for error in errors.errors:
        src, dst, msg = error
        print(f"  Не удалось скопировать '{src}' в '{dst}': {msg}")
except Exception as e:
    print(f"Произошла непредвиденная ошибка: {e}")

В этом примере игнорируются все файлы с расширением .pyc и все файлы/директории, начинающиеся с tmp. Также, используется dirs_exist_ok=True, чтобы избежать FileExistsError, если целевая директория уже существует.

0