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.eth1.ru/www.eth1.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.eth1.ru/www.eth1.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
можно прочитать
здесь