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

---

# 10.9. [`shutil`](https://python-all.ru/3.2/library/shutil.html#module-shutil) – высокоуровневые операции с файлами

**Исходный код:** [Lib/shutil.py](https://python-all.ru/src/3.2/Lib/shutil.py)

---

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

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

## 10.9.1. Операции с каталогами и файлами

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

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

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

Копирует содержимое (без метаданных) файла с именем *src* в файл с именем *dst*. *dst* должно быть полным именем целевого файла; для копирования, принимающего путь к целевому каталогу, см. [`shutil.copy()`](https://python-all.ru/3.2/library/shutil.html#shutil.copy). Если *src* и *dst* совпадают, возбуждается [`Error`](https://python-all.ru/3.2/library/shutil.html#shutil.Error). Целевое местоположение должно быть доступно для записи; в противном случае будет возбуждено исключение [`IOError`](https://python-all.ru/3.2/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)`

Аналогична [`shutil.copy()`](https://python-all.ru/3.2/library/shutil.html#shutil.copy), но также копирует метаданные – фактически это просто [`shutil.copy()`](https://python-all.ru/3.2/library/shutil.html#shutil.copy) с последующим вызовом [`copystat()`](https://python-all.ru/3.2/library/shutil.html#shutil.copystat). Это аналогично команде Unix **cp -p**.

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

Эта фабричная функция создаёт функцию, которую можно использовать в качестве вызываемого объекта для [`copytree()`](https://python-all.ru/3.2/library/shutil.html#shutil.copytree) аргумента *ignore*, игнорируя файлы и каталоги, соответствующие одному из предоставленных шаблонов в стиле glob *patterns*. Смотрите пример ниже.

#### `shutil.copytree(src, dst, symlinks=False, ignore=None, copy_function=copy2, ignore_dangling_symlinks=False)`

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

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

Когда *symlinks* равен False, если файл, на который указывает симлинк, не существует, исключение будет добавлено в список ошибок, возбуждаемых в исключении [`Error`](https://python-all.ru/3.2/library/shutil.html#shutil.Error) в конце процесса копирования. Можно установить необязательный флаг *ignore\_dangling\_symlinks* в значение True, чтобы подавить это исключение. Обратите внимание, что эта опция не действует на платформах, не поддерживающих [`os.symlink()`](https://python-all.ru/3.2/library/os.html#os.symlink).

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

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

Если указан *copy\_function*, это должен быть вызываемый объект, который будет использоваться для копирования каждого файла. Он будет вызван с исходным путём и целевым путём в качестве аргументов. По умолчанию используется [`shutil.copy2()`](https://python-all.ru/3.2/library/shutil.html#shutil.copy2), но можно использовать любую функцию с такой же сигнатурой (например, [`copy()`](https://python-all.ru/3.2/library/copy.html#module-copy)).

Изменено в версии 3.2: Добавлен аргумент *copy\_function*, позволяющий указать собственную функцию копирования.

Изменено в версии 3.2: Добавлен аргумент *ignore\_dangling\_symlinks* для подавления ошибок оборванных символических ссылок, когда *symlinks* равен false.

#### `shutil.rmtree(path, ignore_errors=False, onerror=None)`

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

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

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

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

Если назначение является каталогом или симлинком на каталог, то *src* перемещается внутрь этого каталога.

Целевой каталог не должен уже существовать. Если целевой путь уже существует, но не является каталогом, он может быть перезаписан в зависимости от семантики [`os.rename()`](https://python-all.ru/3.2/library/os.html#os.rename).

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

#### `exception shutil.Error`

Это исключение собирает исключения, возбуждённые во время операции с несколькими файлами. Для [`copytree()`](https://python-all.ru/3.2/library/shutil.html#shutil.copytree) аргумент исключения представляет собой список трёхэлементных кортежей (*srcname*, *dstname*, *исключение*).

### 10.9.1.1. Пример copytree

Этот пример является реализацией функции [`copytree()`](https://python-all.ru/3.2/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)
```

Другой пример, использующий вспомогательную функцию [`ignore_patterns()`](https://python-all.ru/3.2/library/shutil.html#shutil.ignore_patterns):

```python
from shutil import copytree, ignore_patterns

copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
```

Это скопирует все, кроме файлов `.pyc` и файлов или каталогов, имя которых начинается с `tmp`.

Ещё один пример, использующий аргумент *ignore* для добавления вызова журналирования:

```python
from shutil import copytree
import logging

def _logpath(path, names):
    logging.info('Working in %s' % path)
    return []   # ничего не будет проигнорировано

copytree(source, destination, ignore=_logpath)
```

## 10.9.2. Операции архивирования

Также предоставляются высокоуровневые утилиты для создания и чтения сжатых и архивных файлов. Они полагаются на модули [`zipfile`](https://python-all.ru/3.2/library/zipfile.html#module-zipfile) и [`tarfile`](https://python-all.ru/3.2/library/tarfile.html#module-tarfile).

#### `shutil.make_archive(base_name, format[, root_dir[, base_dir[, verbose[, dry_run[, owner[, group[, logger]]]]]]])`

Создаёт архивный файл (например, zip или tar) и возвращает его имя.

*base\_name* – это имя создаваемого файла, включая путь, без расширения, специфичного для формата. *format* – это формат архива: один из «zip», «tar», «bztar» (если доступен модуль [`bz2`](https://python-all.ru/3.2/library/bz2.html#module-bz2)) или «gztar».

*root\_dir* – это каталог, который будет корневым каталогом архива; например, мы обычно переходим в *root\_dir* перед созданием архива.

*base\_dir* – это каталог, из которого начинается архивирование; т.е. *base\_dir* будет общим префиксом всех файлов и каталогов в архиве.

*root\_dir* и *base\_dir* по умолчанию равны текущему каталогу.

*owner* и *group* используются при создании tar-архива. По умолчанию используются текущий владелец и группа.

*logger* должен быть объектом, совместимым с [**PEP 282**](https://python-all.ru/3.2/library/shutil.html), обычно экземпляром [`logging.Logger`](https://python-all.ru/3.2/library/logging.html#logging.Logger).

Новое в версии 3.2.

#### `shutil.get_archive_formats()`

Возвращает список поддерживаемых форматов архивирования. Каждый элемент возвращаемой последовательности – кортеж `(name, description)`

По умолчанию [`shutil`](https://python-all.ru/3.2/library/shutil.html#module-shutil) предоставляет следующие форматы:

- *gztar*: tar-файл, сжатый gzip
- *bztar*: tar-файл, сжатый bzip2 (если доступен модуль [`bz2`](https://python-all.ru/3.2/library/bz2.html#module-bz2)).
- *tar*: несжатый tar-файл
- *zip*: ZIP-файл

Можно зарегистрировать новые форматы или предоставить собственный архиватор для любых существующих форматов, используя [`register_archive_format()`](https://python-all.ru/3.2/library/shutil.html#shutil.register_archive_format).

Новое в версии 3.2.

#### `shutil.register_archive_format(name, function[, extra_args[, description]])`

Регистрирует архиватор для формата *name*. *function* – это вызываемый объект, который будет использоваться для вызова архиватора.

Если задано, *extra\_args* – это последовательность пар `(name, value)`, которые будут использоваться как дополнительные именованные аргументы при вызове архиватора.

*description* используется функцией [`get_archive_formats()`](https://python-all.ru/3.2/library/shutil.html#shutil.get_archive_formats), которая возвращает список архиваторов. По умолчанию – пустой список.

Новое в версии 3.2.

#### `shutil.unregister_archive_format(name)`

Удалите имя формата архива *name* из списка поддерживаемых форматов.

Новое в версии 3.2.

#### `shutil.unpack_archive(filename[, extract_dir[, format]])`

Распаковывает архив. *filename* – это полный путь к архиву.

*extract\_dir* – имя целевой директории, в которую распаковывается архив. Если не указано, используется текущая рабочая директория.

*format* – это формат архива: один из «zip», «tar» или «gztar». Или любой другой формат, зарегистрированный с помощью [`register_unpack_format()`](https://python-all.ru/3.2/library/shutil.html#shutil.register_unpack_format). Если не указан, [`unpack_archive()`](https://python-all.ru/3.2/library/shutil.html#shutil.unpack_archive) использует расширение имени файла архива и проверяет, зарегистрирован ли распаковщик для этого расширения. Если ни один не найден, возбуждается [`ValueError`](https://python-all.ru/3.2/library/exceptions.html#ValueError).

Новое в версии 3.2.

#### `shutil.register_unpack_format(name, extensions, function[, extra_args[, description]])`

Регистрирует формат распаковки. *name* – это имя формата, а *extensions* – список расширений, соответствующих формату, например `.zip` для Zip-файлов.

*function* – это вызываемый объект, который будет использоваться для распаковки архивов. Вызываемый объект будет получать путь к архиву, за которым следует каталог, в который необходимо извлечь архив.

Если указано, *extra\_args* – это последовательность кортежей `(name, value)`, которые будут переданы как именованные аргументы вызываемому объекту.

*description* может быть указан для описания формата и будет возвращён функцией [`get_unpack_formats()`](https://python-all.ru/3.2/library/shutil.html#shutil.get_unpack_formats).

Новое в версии 3.2.

#### `shutil.unregister_unpack_format(name)`

Отменяет регистрацию формата распаковки. *name* – имя формата.

Новое в версии 3.2.

#### `shutil.get_unpack_formats()`

Возвращает список всех зарегистрированных форматов распаковки. Каждый элемент возвращаемой последовательности – это кортеж `(name, extensions, description)`.

По умолчанию [`shutil`](https://python-all.ru/3.2/library/shutil.html#module-shutil) предоставляет следующие форматы:

- *gztar*: tar-файл, сжатый gzip
- *bztar*: tar-файл, сжатый bzip2 (если доступен модуль [`bz2`](https://python-all.ru/3.2/library/bz2.html#module-bz2)).
- *tar*: несжатый tar-файл
- *zip*: ZIP-файл

Можно зарегистрировать новые форматы или предоставить собственный распаковщик для любых существующих форматов, используя [`register_unpack_format()`](https://python-all.ru/3.2/library/shutil.html#shutil.register_unpack_format).

Новое в версии 3.2.

### 10.9.2.1. Пример архивирования

В этом примере создаётся tar-архив, сжатый gzip, содержащий все файлы, найденные в каталоге пользователя `.ssh`:

```python
>>> from shutil import make_archive
>>> import os
>>> archive_name = os.path.expanduser(os.path.join('~', 'myarchive'))
>>> root_dir = os.path.expanduser(os.path.join('~', '.ssh'))
>>> make_archive(archive_name, 'gztar', root_dir)
'/Users/tarek/myarchive.tar.gz'
```

Полученный архив содержит:

```python
$ tar -tzvf /Users/tarek/myarchive.tar.gz
drwx------ tarek/staff       0 2010-02-01 16:23:40 ./
-rw-r--r-- tarek/staff     609 2008-06-09 13:26:54 ./authorized_keys
-rwxr-xr-x tarek/staff      65 2008-06-09 13:26:54 ./config
-rwx------ tarek/staff     668 2008-06-09 13:26:54 ./id_dsa
-rwxr-xr-x tarek/staff     609 2008-06-09 13:26:54 ./id_dsa.pub
-rw------- tarek/staff    1675 2008-06-09 13:26:54 ./id_rsa
-rw-r--r-- tarek/staff     397 2008-06-09 13:26:54 ./id_rsa.pub
-rw-r--r-- tarek/staff   37192 2010-02-06 18:23:10 ./known_hosts
```
