shutil Python
Введение | |
Варианты копирования | |
copyfile | |
copy | |
move | |
Удалить содержимое директории | |
Похожие статьи |
Введение
В этой статье вы узнаете как работать с несколькими файлами одновременно с помощью shutil.
Перед изучением данной статьи рекомендую убедиться, что вы знакомы с материалом из статьи
os
,
особенно часть про
listdir()
Оффициальная документация
Копирование
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.testsetup.ru/www.testsetup.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.testsetup.ru/www.testsetup.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/ ├── copy_ex.py ├── dir_a │ ├── Armenia.html │ ├── Finland.html │ ├── Spain │ └── Sweden.html └─ dir_b
Попробуем скопировать содержимое dir_a в dir_b с помощью shutil.copy()
import shutil import os src = "/mnt/c/Users/Andrei/dir_a" dst = "/mnt/c/Users/Andrei/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dst) print(dir_b_files) os.chdir(src) for file in dir_a_files: shutil.copy(file, dst)
['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] [] Traceback (most recent call last): File "/mnt/c/Users/Andrei/python/shutil_ex.py", line 16, in <module> shutil.copy(file, dst) 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/dir_a" dst = "/mnt/c/Users/Andrei/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dst) print(dir_b_files) os.chdir(src) for file in dir_a_files: if os.path.isfile(file): shutil.copy(file, dst)
python shutil_ex.py
['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] []
ls dir_b/
Armenia.html Finland.html Sweden.html
Если в директории назначения были файлы с такими же именами как у копируемых, то они будут перезаписаны.
move
import shutil import os src = "/mnt/c/Users/Andrei/dir_a" dst = "/mnt/c/Users/Andrei/dir_b" dir_a_files = os.listdir(src) for file in dir_a_files: if os.path.isfile(file): shutil.move(file, dst)
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/python/shutil_ex.py", line 18, in <module> shutil.move(file, dst) 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/dir_b/Armenia.html' already exists
Заставить файлы быть перезаписанными можно задав полные пути с помощью os.path.join()
import shutil import os src = "/mnt/c/Users/Andrei/dir_a" dst = "/mnt/c/Users/Andrei/dir_b" dir_a_files = os.listdir(src) print(dir_a_files) dir_b_files = os.listdir(dst) print(dir_b_files) os.chdir(src) for file in dir_a_files: if os.path.isfile(file): print(dst) full_dst = os.path.join(dst, file) print(full_dst) print() shutil.move(file, full_dst)
['Armenia.html', 'Finland.html', 'Spain', 'Sweden.html'] ['Armenia.html', 'Finland.html', 'Sweden.html'] /mnt/c/Users/Andrei/dir_b /mnt/c/Users/Andrei/dir_b/Armenia.html /mnt/c/Users/Andrei/dir_b /mnt/c/Users/Andrei/dir_b/Finland.html /mnt/c/Users/Andrei/dir_b /mnt/c/Users/Andrei/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
можно прочитать
здесь