shutil Python

Содержание
Введение
Варианты копирования
copyfile
copy
move
Удалить содержимое директории
Похожие статьи

Введение

В этой статье вы узнаете как работать с несколькими файлами одновременно с помощью shutil.

Перед изучением данной статьи рекомендую убедиться, что вы знакомы с материалом из статьи os

Оффициальная документация

Копирование

copyfile() копирует только контент файла
copy() copyfile() + права доступа + назначением может быть директория
copy2() copy() + метадата (время создания и изменения файла)

copyfile

Синтаксис

shutil.copyfile(src, dst, *, follow_symlinks=True)

Описание

Копирует содержимое (без метаданных) файла с именем src в файл с именем dst и верните dst наиболее эффективным из возможных способов. src и dst - это объекты, подобные пути, или имена путей, заданные в виде строк.

dst должно быть полным именем целевого файла; посмотрите на copy() для получения копии, которая принимает путь к целевому каталогу. Если src и dst указывают один и тот же файл, возникает ошибка SameFileError.

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

Если значение follow_symlinks равно false, а src является символической ссылкой, то вместо копирования файла, на который указывает src, будет создана новая символическая ссылка.

Вызывает событие аудита shutil.copyfile с аргументами src, dst.

Изменено в версии 3.3: раньше вызывался IOError вместо OSError. Добавлен аргумент follow_symlinks. Теперь возвращает летнее время.

Изменено в версии 3.4: Вызывается SameFileError вместо Error. Поскольку первый является подклассом второго, это изменение обратно совместимо.

Изменено в версии 3.8: Системные вызовы быстрого копирования, специфичные для конкретной платформы, могут использоваться внутри системы для более эффективного копирования файла. Смотрите раздел "Эффективные операции копирования, зависящие от платформы" .

Пример

shutil/ └── source.txt

cat source.txt

Welcome to www.urn.su/www.andreyolegovich.ru!

import shutil shutil.copyfile('source.txt', 'destination.txt')

Новый файл destination.txt появится в той же директории.

shutil/ ├── destination.txt └── source.txt

Проверить содержимое можно командой cat (в Linux и Unix ) или командой notepad (в Windows )

cat destination.txt

Welcome to www.urn.su/www.andreyolegovich.ru!

copy

Синтаксис

shutil.copy(src, dst, *, follow_symlinks=True)

Описание

Копирует файл src в файл или каталог dst.

src и dst должны быть объектами, подобными пути, или строками.

Если в качестве dst задан каталог, файл будет скопирован в dst, используя базовое имя файла из src.

Если в качестве dst указан файл, который уже существует, он будет заменен. Возвращает путь ко вновь созданному файлу.

Если значение follow_symlinks равно false, а src является символической ссылкой, dst будет создан как символическая ссылка.

Если значение follow_symlinks равно true и src является символической ссылкой, dst будет копией файла, на который ссылается src.

copy() копирует данные файла и режим разрешения файла (см. os.chmod()). Другие метаданные, такие как время создания и модификации файла, не сохраняются.

Чтобы сохранить все метаданные файла из оригинала, вместо этого используйте copy2().

Вызывает событие аудита shutil.copyfile с аргументами src, dst.

Вызывает событие аудита shutil.copymode с аргументами src, dst.

Изменено в версии 3.3: добавлен аргумент follow_symlinks. Теперь возвращает путь к вновь созданному файлу.

Изменено в версии 3.8: Системные вызовы быстрого копирования, специфичные для конкретной платформы, могут использоваться внутри системы для более эффективного копирования файла. Смотрите раздел "Эффективные операции копирования, зависящие от платформы".

Пример

Предположим, что мы находимся в директории python:

python/ ├── dir_a │ ├── Armenia.html │ ├── Finland.html │ ├── Spain │ └── Sweden.html └─ dir_b

import shutil import os src = "/mnt/c/Users/Andrei/sandbox/python/dir_a" dest = "/mnt/c/Users/Andrei/sandbox/python/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dest) print(dir_b_files) os.chdir(src) for file in dir_a_files: with open(file) as f: print(file, f.read())

python shutil_ex.py

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] ['Armenia.html', 'Finland.html', 'Sweden.html'] Armenia.html tickets to Armenia hotels in Armenia Finland.html tickets to Finland hotels in Finland Traceback (most recent call last): File "/mnt/c/Users/Andrei/sandbox/python/shutil_ex1.py", line 16, in <module> with open(file) as f: ^^^^^^^^^^ IsADirectoryError: [Errno 21] Is a directory: 'Spain'

Открыть директорию как файл не получилось

import shutil import os src = "/mnt/c/Users/Andrei/sandbox/python/dir_a" dest = "/mnt/c/Users/Andrei/sandbox/python/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dest) print(dir_b_files) os.chdir(src) for file in dir_a_files: shutil.copy(file, dest)

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] [] Traceback (most recent call last): File "/mnt/c/Users/Andrei/sandbox/python/shutil_ex.py", line 16, in <module> shutil.copy(file, dest) File "/usr/local/lib/python3.11/shutil.py", line 419, in copy copyfile(src, dst, follow_symlinks=follow_symlinks) File "/usr/local/lib/python3.11/shutil.py", line 256, in copyfile with open(src, 'rb') as fsrc: ^^^^^^^^^^^^^^^ IsADirectoryError: [Errno 21] Is a directory: 'Spain'

Несмотря на ошибку, вызванную невозможностью скопировать директорию, обычные файлы которые шли по списку раньше чем Spain успели скопироваться.

ls dir_b/

Armenia.html Finland.html

Чтобы не получать ошибки из-за директорий воспользуемся проверкой на тип файла os.paht.isfile которая может определить является ли файл обычным файлом а не директорией.

import shutil import os src = "/mnt/c/Users/Andrei/sandbox/python/dir_a" dest = "/mnt/c/Users/Andrei/sandbox/python/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dest) print(dir_b_files) os.chdir(src) for file in dir_a_files: if os.path.isfile(file): shutil.copy(file, dest)

python shutil_ex.py

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] []

ls dir_b/

Armenia.html Finland.html Sweden.html

Если в директории назначения были файлы с такими же именами как у копируемых, то они будут перезаписаны.

move

for file in dir_a_files: if os.path.isfile(file): shutil.move(file, dest)

python shutil_ex.py

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] []

ls dir_a

Spain

ls dir_b

Armenia.html Finland.html Sweden.html

Если бы такие файлы уже были в директории назначения, то получилась бы ошибка

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] ['Armenia.html', 'Finland.html', 'Sweden.html'] Traceback (most recent call last): File "/mnt/c/Users/Andrei/sandbox/python/shutil_ex.py", line 18, in <module> shutil.move(file, dest) File "/usr/local/lib/python3.11/shutil.py", line 823, in move raise Error("Destination path '%s' already exists" % real_dst) shutil.Error: Destination path '/mnt/c/Users/Andrei/sandbox/python/dir_b/Armenia.html' already exists

Заставить файлы быть перезаписанными можно задав полные пути с помощью os.path.join()

import shutil import os src = "/mnt/c/Users/Andrei/sandbox/python/dir_a" dest = "/mnt/c/Users/Andrei/sandbox/python/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dest) print(dir_b_files) os.chdir(src) for file in dir_a_files: if os.path.isfile(file): print(dest) full_dest = os.path.join(dest, file) print(full_dest) print() shutil.move(file, full_dest)

['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] ['Armenia.html', 'Finland.html', 'Sweden.html'] /mnt/c/Users/Andrei/sandbox/python/dir_b /mnt/c/Users/Andrei/sandbox/python/dir_b/Armenia.html /mnt/c/Users/Andrei/sandbox/python/dir_b /mnt/c/Users/Andrei/sandbox/python/dir_b/Finland.html /mnt/c/Users/Andrei/sandbox/python/dir_b /mnt/c/Users/Andrei/sandbox/python/dir_b/Sweden.html

ls dir_a

Spain

ls dir_b

Armenia.html Finland.html Sweden.html

Удалить содержимое директории

Чтобы очистить директорию с помощью Python нужно воспользоваться shutil и os

import shutil import os def delete_dir_content(path: str): for file in os.listdir(path): file_path = os.path.join(path, file) try: if os.path.isfile(file_path) or os.path.islink(file_path): os.unlink(file_path) elif os.path.isdir(file_path): shutil.rmtree(file_path) except Exception as e: print(f"Failed to delete {file_path}. Reason: {e}")

Про deep copy и shallow copy в программировании можно прочитать здесь

Про функцию copy() в Python можно прочитать здесь

Похожие статьи
Работа с файлами в Python
Python
Основы работы с файлами
Продвинутые приёмы
glob: Работа с несколькими файлами
os
pathlib
Скачать файл по сети
psutil: cистемные ресурсы
Обучение программированию на Python