> **Источник:** https://python-all.ru/3.1/library/shutil.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 10.9. `shutil` – высокоуровневые операции с файлами

Модуль `shutil` предоставляет ряд высокоуровневых операций над файлами и наборами файлов. В частности, предоставляются функции для копирования и удаления файлов. Для операций с отдельными файлами см. также модуль [`os`](https://python-all.ru/3.1/library/os.html#module-os).

> **Предупреждение**
>
> Даже более высокоуровневые функции копирования файлов ([`copy()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy), [`copy2()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy2)) не могут копировать все метаданные файлов.
>
> На платформах POSIX это означает, что владелец и группа файла теряются, а также ACL. На Mac OS не используются ресурсные форки и другие метаданные. Это означает, что ресурсы будут потеряны, а коды типа и создателя файла будут некорректными. В Windows владельцы файлов, ACL и альтернативные потоки данных не копируются.

#### `shutil.copyfileobj(fsrc, fdst[, length])`

Копирует содержимое файлоподобного объекта

*fsrc*

в файлоподобный объект

*fdst*

. Целое число

*length*

, если задано, определяет размер буфера. В частности, отрицательное значение

*length*

означает копирование данных без разбиения исходных данных на части; по умолчанию данные читаются порциями, чтобы избежать неконтролируемого расхода памяти. Обратите внимание: если текущая позиция в файле объекта

*fsrc*

не равна 0, будут скопированы только данные от текущей позиции до конца файла.

#### `shutil.copyfile(src, dst)`

Копирует содержимое (без метаданных) файла с именем

*src*

в файл с именем

*dst*

.

*dst*

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

[`copy()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy)

. Если

*src*

и

*dst*

– один и тот же файл, вызывается

[`Error`](https://python-all.ru/3.1/library/shutil.html#shutil.Error)

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

[`IOError`](https://python-all.ru/3.1/library/exceptions.html#IOError)

. Если

*dst*

уже существует, он будет заменён. Специальные файлы, такие как символьные или блочные устройства и каналы, не могут быть скопированы этой функцией.

*src*

и

*dst*

– имена путей, заданные в виде строк.

#### `shutil.copymode(src, dst)`

Копирует биты разрешений из

*src*

в

*dst*

. Содержимое файла, владелец и группа не изменяются.

*src*

и

*dst*

– пути, заданные в виде строк.

#### `shutil.copystat(src, dst)`

Копирует биты разрешений, время последнего доступа, время последнего изменения и флаги из

*src*

в

*dst*

. Содержимое файла, владелец и группа не изменяются.

*src*

и

*dst*

– пути, заданные в виде строк.

#### `shutil.copy(src, dst)`

Копирует файл

*src*

в файл или каталог

*dst*

. Если

*dst*

– каталог, в указанном каталоге создаётся (или перезаписывается) файл с тем же базовым именем, что и

*src*

. Биты разрешений копируются.

*src*

и

*dst*

– пути, заданные в виде строк.

#### `shutil.copy2(src, dst)`

Аналогична

[`copy()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy)

, но копирует также метаданные – по сути, это

[`copy()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy)

с последующим вызовом

[`copystat()`](https://python-all.ru/3.1/library/shutil.html#shutil.copystat)

. Похожа на команду Unix

**cp -p**

.

#### `shutil.ignore_patterns(*patterns)`

Эта фабричная функция создаёт функцию, которую можно использовать в качестве вызываемого объекта для

[`copytree()`](https://python-all.ru/3.1/library/shutil.html#shutil.copytree)

аргумента

*ignore*

, игнорируя файлы и каталоги, соответствующие одному из предоставленных шаблонов в стиле glob

*patterns*

. Смотрите пример ниже.

#### `shutil.copytree(src, dst[, symlinks=False[, ignore=None]])`

Рекурсивно копирует всё дерево каталогов с корнем в *src*. Целевой каталог, заданный именем *dst*, не должен существовать; он будет создан вместе с недостающими родительскими каталогами. Права доступа и временные метки каталогов копируются с помощью [`copystat()`](https://python-all.ru/3.1/library/shutil.html#shutil.copystat), отдельные файлы копируются с помощью [`copy2()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy2).

Если *symlinks* равно true, символические ссылки в исходном дереве представляются как символические ссылки в новом дереве; если false или параметр опущен, содержимое файлов, на которые указывают ссылки, копируется в новое дерево.

Если задан *ignore*, он должен быть вызываемым объектом, который будет получать в качестве аргументов каталог, посещаемый функцией [`copytree()`](https://python-all.ru/3.1/library/shutil.html#shutil.copytree), и список его содержимого, возвращаемый функцией [`os.listdir()`](https://python-all.ru/3.1/library/os.html#os.listdir). Поскольку [`copytree()`](https://python-all.ru/3.1/library/shutil.html#shutil.copytree) вызывается рекурсивно, вызываемый объект *ignore* будет вызываться один раз для каждого копируемого каталога. Вызываемый объект должен возвращать последовательность имён каталогов и файлов относительно текущего каталога (т.е. подмножество элементов своего второго аргумента); эти имена затем будут игнорироваться в процессе копирования. [`ignore_patterns()`](https://python-all.ru/3.1/library/shutil.html#shutil.ignore_patterns) можно использовать для создания такого вызываемого объекта, который игнорирует имена на основе шаблонов в стиле glob.

Если возникнут исключения, возбуждается исключение [`Error`](https://python-all.ru/3.1/library/shutil.html#shutil.Error) со списком причин.

Данный исходный код следует рассматривать скорее как пример, а не как универсальный инструмент.

#### `shutil.rmtree(path[, ignore_errors[, onerror]])`

Удаляет целое дерево каталогов; *path* должен указывать на каталог (но не на символическую ссылку на каталог). Если *ignore\_errors* равен true, ошибки, возникающие при неудачном удалении, игнорируются; если false или не указан, такие ошибки обрабатываются вызовом обработчика, заданного *onerror*, или, если он не указан, вызывается исключение.

Если указан *onerror*, это должен быть вызываемый объект, принимающий три параметра: *function*, *path* и *excinfo*. Первый параметр, *function*, – это функция, возбудившая исключение; это может быть [`os.path.islink()`](https://python-all.ru/3.1/library/os.path.html#os.path.islink), [`os.listdir()`](https://python-all.ru/3.1/library/os.html#os.listdir), [`os.remove()`](https://python-all.ru/3.1/library/os.html#os.remove) или [`os.rmdir()`](https://python-all.ru/3.1/library/os.html#os.rmdir). Второй параметр, *path*, – это имя пути, переданное *function*. Третий параметр, *excinfo*, – это информация об исключении, возвращаемая [`sys.exc_info()`](https://python-all.ru/3.1/library/sys.html#sys.exc_info). Исключения, возбуждённые *onerror*, не перехватываются.

#### `shutil.move(src, dst)`

Рекурсивно перемещает файл или каталог в другое место.

Если целевой объект находится в той же файловой системе, просто используется rename. В противном случае src копируется (с помощью [`copy2()`](https://python-all.ru/3.1/library/shutil.html#shutil.copy2)) в dst, а затем src удаляется.

#### `exception shutil.Error`

Это исключение собирает исключения, возникшие во время операции с несколькими файлами. Для

[`copytree()`](https://python-all.ru/3.1/library/shutil.html#shutil.copytree)

аргумент исключения представляет собой список кортежей из трёх элементов (

*srcname*

,

*dstname*

,

*exception*

).

## 10.9.1. Пример

Этот пример является реализацией функции [`copytree()`](https://python-all.ru/3.1/library/shutil.html#shutil.copytree), описанной выше, с опущенной строкой документации. Он демонстрирует многие другие функции, предоставляемые этим модулем.

```python
def copytree(src, dst, symlinks=False):
    names = os.listdir(src)
    os.makedirs(dst)
    errors = []
    for name in names:
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks)
            else:
                copy2(srcname, dstname)
            # XXX Что насчет устройств, сокетов и т.д.?
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # перехватываем ошибку от рекурсивного copytree, чтобы мы могли
        # продолжить с другими файлами
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        # не удается скопировать время доступа к файлам в Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)
```
