В этом разделе приводятся примеры использования функций модуля shutil
, которые выполняют высокоуровневые файловые операции, такие как копирование, удаление и архивирование.
shutil.copytree()
Функция shutil.copyfile()
копирует содержимое источника в место назначения и вызывает исключение IOError
, если у него нет разрешения на запись в файл назначения.
>>> import shutil, os >>> from glob import glob # создадим временную директорию >>> os.mkdir('example') # создадим тестовый файл >>> open('example/test_file.txt', 'w').close() # копирование >>> shutil.copyfile('example/test_file.txt', 'example/test_file.txt.copy') # 'example/test-file.txt.copy' # смотрим результат >>> pprint.pprint(glob('example/*')) # ['example/test_file.txt.copy', 'example/test_file.txt'] # удаляем >>> shutil.rmtree('example')
Функция shutil.copy()
интерпретирует имя выходного файла как инструмент командной строки Unix cp
. Если путь назначения указан как каталог, а не файл, то в каталоге создается новый файл с использованием его базового имени.
>>> import shutil, os >>> from glob import glob # создадим тестовый файл >>> open('shutil_copy.txt', 'w').close() # создадим временную директорию >>> os.mkdir('example') >>> glob('example/*') # [] # копируем >>> shutil.copy('shutil_copy.txt', 'example') # 'example/shutil_copy.txt' # смотрим результат >>> glob('example/*') # ['example/shutil_copy.txt'] # удаляем >>> shutil.rmtree('example')
Функция shutil.copytree()
рекурсивно копирует весь каталог.
# для того что бы протестировать функцию copytree() # создадим иерархию каталогов import pathlib, itertools, glob, shutil path = 'test/' tmp = {'script':'.py', 'text':'.txt'} for d, ext in tmp.items(): comb = itertools.combinations([d, 1, 0], r=2) for a, b in comb: name = f'{a}{b}{ext}' pathlib.Path(path, d).mkdir(parents=True, exist_ok=True) pathlib.Path(path, d, name).touch(exist_ok=True) f = glob.glob('test/**/*', recursive=True) print(f) # ['test/text', 'test/script', 'test/text/10.txt', # 'test/text/text1.txt', 'test/text/text0.txt', # 'test/script/10.py', 'test/script/script0.py', # 'test/script/script1.py'] # копируем shutil.copytree('test', 'test_cp') # смотрим результат f_cp = glob.glob('test_cp/**/*', recursive=True) print(f_cp) # ['test/text', 'test/script', 'test/text/10.txt', # 'test/text/text1.txt', 'test/text/text0.txt', # 'test/script/10.py', 'test/script/script0.py', # 'test/script/script1.py'] # удаляем shutil.rmtree('test_cp') shutil.rmtree('test')
Пример, который использует помощник shutil.ignore_patterns()
. Здесь копируется все, кроме файлов .pyc
и файлов или каталогов, чье имя начинается с tmp
.
from shutil import copytree, ignore_patterns copytree(source, destination, ignore=ignore_patterns('*.pyc', 'tmp*'))
Другой пример, который использует аргумент ignore
для добавления вызова логирования копирования файлов:
from shutil import copytree import logging def _logpath(path, names): logging.info('Working in %s', path) return [] # nothing will be ignored copytree(source, destination, ignore=_logpath)
Работа функции shutil.rmtree()
, которая выполняет рекурсивное удаление каталога, демонстрировалась выше. Разберем ситуации посложнее.
В этом примере показано, как удалить дерево каталогов в Windows, где для некоторых файлов установлен бит только для чтения. Он использует обратный вызов onerror
, чтобы очистить бит readonly
и повторить попытку удаления.
import os, stat import shutil def remove_readonly(func, path, _): "Clear the readonly bit and reattempt the removal" os.chmod(path, stat.S_IWRITE) func(path) shutil.rmtree(directory, onerror=remove_readonly)
В функции shutil.rmtree()
, так же можно использовать помощник shutil.ignore_patterns()
для выборочного рекурсивного удаления файлов как это делается в выборочном рекурсивном копировании файлов.
shutil.copytree()
:Этот пример является реализацией функции shutil.copytree()
, с опущенной строкой документации. Он демонстрирует многие другие функции, предоставляемые этим модулем.
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 What about devices, sockets etc.? except OSError as why: errors.append((srcname, dstname, str(why))) # catch the Error from the recursive copytree so that we can # continue with other files except Error as err: errors.extend(err.args[0]) try: copystat(src, dst) except OSError as why: # can't copy file access times on Windows if why.winerror is None: errors.extend((src, dst, str(why))) if errors: raise Error(errors)
В этом примере создадим архив tar-файлов с использованием gzip
, содержащий все файлы, найденные в каталоге .ssh
пользователя:
>>> 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/docs-python/myarchive.tar.gz'
Полученный архив содержит:
~$ tar -tzvf /home/docs-python/myarchive.tar.gz drwx------ docs-python/docs-python 0 2019-12-17 16:57 ./ -rw------- docs-python/docs-python 1554 2019-12-17 16:53 ./known_hosts -rw------- docs-python/docs-python 1554 2019-12-17 14:06 ./known_hosts.old -rw------- docs-python/docs-python 1679 2019-09-16 12:02 ./id_rsa -rw-r--r-- docs-python/docs-python 399 2019-09-16 12:02 ./id_rsa.pub