Shutil.copy: примеры (PYTHON)

Функция shutil.copy для работы с файлами в Python
Раздел: Файловая система, Копирование файлов
shutil.copy(src, dst, follow_symlinks): str

Описание функции shutil.copy

Функция shutil.copy() в Python используется для копирования содержимого файла из одного местоположения в другое. Она входит в стандартный модуль shutil (утилиты для работы с оболочкой). Основное применение - копирование отдельных файлов, когда не требуется сохранять метаданные, такие как временные метки или права доступа.

Аргументы функции

  • src (строка или объект, подобный пути): путь к исходному файлу, который необходимо скопировать. Это обязательный аргумент.
  • dst (строка или объект, подобный пути): путь назначения. Может быть именем файла или каталогом. Если dst указывает на каталог, файл будет скопирован в этот каталог с сохранением исходного имени. Если dst указывает на файл, копирование произойдет с новым именем. Это обязательный аргумент.
  • follow_symlinks (булево значение, необязательный): если значение True (по умолчанию), функция следует за символическими ссылками в исходном пути. Если False и src является символической ссылкой, будет создана новая символическая ссылка, а не скопировано содержимое файла.

Возвращаемое значение

Функция возвращает строку, представляющую путь к скопированному файлу (тот же, что и переданный в dst).

Примеры использования shutil.copy

Базовое копирование файла

import shutil
import os

# Копирование файла с сохранением имени в текущем каталоге
shutil.copy('source.txt', 'destination.txt')
print(f'Файл создан: {os.path.exists("destination.txt")}')
Файл создан: True

Копирование в директорию

import shutil
import os

# Создаем директорию, если ее нет
os.makedirs('backup', exist_ok=True)
# Копируем файл в директорию 'backup' с сохранением имени
result_path = shutil.copy('report.pdf', 'backup')
print(f'Скопировано в: {result_path}')
Скопировано в: backup\report.pdf

Копирование с параметром follow_symlinks=False

import shutil
import os

# Создаем символическую ссылку (на Unix-системах)
if os.name != 'nt':
    os.symlink('real_file.txt', 'link_file.txt')
    # Копируем ссылку как ссылку, а не файл
    shutil.copy('link_file.txt', 'copied_link.txt', follow_symlinks=False)
    # Проверяем, является ли копия ссылкой
    print(f'Копия - символическая ссылка: {os.path.islink("copied_link.txt")}')
Копия - символическая ссылка: True

Похожие функции в Python

Модуль shutil предлагает несколько функций для копирования:

  • shutil.copy2() - копирует файл, сохраняя метаданные (время последнего доступа и модификации). Используется, когда важна информация о времени изменения файла.
  • shutil.copyfile() - копирует содержимое файла в другой файл без поддержки копирования в директорию или обработки метаданных. Более низкоуровневая функция.
  • shutil.copytree() - рекурсивно копирует целое дерево каталогов. Применяется для копирования папок со всем содержимым.
  • os.popen() или subprocess.run() с вызовом системных команд (например, cp на Unix) - дают полный контроль над процессом копирования, но менее переносимы.

Выбор функции зависит от задачи: shutil.copy() подходит для быстрого копирования файлов без метаданных, shutil.copy2() - для случаев, когда нужно сохранить временные метки, а shutil.copytree() - для копирования директорий.

Аналоги функции в других языках

JavaScript (Node.js)

Используется модуль fs с функцией copyFile(). Работает асинхронно.

const fs = require('fs/promises');

async function copyFileExample() {
    await fs.copyFile('source.txt', 'destination.txt');
    console.log('Файл скопирован');
}
copyFileExample();
Файл скопирован

Java

Класс Files с методом copy(). Требует указания пути через Path объекты.

import java.nio.file.*;

public class Main {
    public static void main(String[] args) throws Exception {
        Path source = Paths.get("source.txt");
        Path destination = Paths.get("destination.txt");
        Files.copy(source, destination, StandardCopyOption.REPLACE_EXISTING);
        System.out.println("Файл скопирован");
    }
}
Файл скопирован

PHP

Функция copy(). Проста в использовании, но не поддерживает дополнительные флаги.

<?php
copy('source.txt', 'destination.txt');
echo "Файл скопирован";
?>
Файл скопирован

C#

Метод File.Copy() из пространства имен System.IO.

using System.IO;

class Program {
    static void Main() {
        File.Copy("source.txt", "destination.txt", overwrite: true);
        System.Console.WriteLine("Файл скопирован");
    }
}
Файл скопирован

Golang

Используется функция Copy() из пакета io или CopyFile() из os.

package main

import (
    "io"
    "os"
)

func main() {
    source, _ := os.Open("source.txt")
    destination, _ := os.Create("destination.txt")
    io.Copy(destination, source)
    source.Close()
    destination.Close()
    println("Файл скопирован")
}
Файл скопирован

Типичные ошибки при использовании

Файл источника не существует

import shutil
import traceback

try:
    shutil.copy('несуществующий_файл.txt', 'destination.txt')
except FileNotFoundError as e:
    print(f'Ошибка: {e}')
Ошибка: [Errno 2] No such file or directory: 'несуществующий_файл.txt'

Отсутствие прав на чтение исходного файла

import shutil
import os

# Создаем файл без прав на чтение (Unix-системы)
if os.name != 'nt':
    with open('protected.txt', 'w') as f:
        f.write('секрет')
    os.chmod('protected.txt', 0o000)  # Нет прав
    try:
        shutil.copy('protected.txt', 'copy.txt')
    except PermissionError as e:
        print(f'Ошибка прав: {e}')
    finally:
        os.chmod('protected.txt', 0o644)  # Восстановление прав
        os.remove('protected.txt')
Ошибка прав: [Errno 13] Permission denied: 'protected.txt'

Копирование в несуществующую директорию

import shutil

try:
    shutil.copy('source.txt', 'несуществующая_папка/copy.txt')
except FileNotFoundError as e:
    print(f'Ошибка: {e}')
Ошибка: [Errno 2] No such file or directory: 'несуществующая_папка/copy.txt'

Изменения в последних версиях Python

Функция shutil.copy() стабильна и не претерпела значительных изменений в последних основных версиях Python. Однако с версии Python 3.3 функция поддерживает аргумент follow_symlinks, который позволяет контролировать обработку символических ссылок. В Python 3.8 улучшена обработка ошибок при работе с специальными файлами (например, символьными устройствами в Unix). Также, начиная с Python 3.10, улучшены сообщения об ошибках для некоторых сценариев, связанных с правами доступа.

Расширенные примеры использования

Копирование с проверкой размера файла

Пример python
import shutil
import os

def copy_if_small(src, dst, max_size=1024*1024):  # 1 MB
    if os.path.getsize(src) <= max_size:
        return shutil.copy(src, dst)
    else:
        raise ValueError(f'Файл {src} превышает максимальный размер {max_size} байт')

# Пример использования
try:
    result = copy_if_small('large_video.mp4', 'backup.mp4', max_size=5000000)
    print(f'Успешно скопирован: {result}')
except ValueError as e:
    print(f'Ошибка: {e}')
Ошибка: Файл large_video.mp4 превышает максимальный размер 5000000 байт

Копирование с ведением лога

Пример python
import shutil
import logging
import datetime

logging.basicConfig(filename='copy_log.log', level=logging.INFO)

def logged_copy(src, dst):
    try:
        result = shutil.copy(src, dst)
        logging.info(f'{datetime.datetime.now()}: Успешное копирование из {src} в {dst}')
        return result
    except Exception as e:
        logging.error(f'{datetime.datetime.now()}: Ошибка при копировании {src} -> {dst}: {e}')
        raise

# Пример
logged_copy('data.csv', 'backup/data.csv')
# В файле copy_log.log появится запись:
# 2023-10-05 14:30:15.123456: Успешное копирование из data.csv в backup/data.csv

Копирование файлов только определенного типа

Пример python
import shutil
import os

def copy_only_ext(src_dir, dst_dir, extension):
    os.makedirs(dst_dir, exist_ok=True)
    for filename in os.listdir(src_dir):
        if filename.endswith(extension):
            src_path = os.path.join(src_dir, filename)
            dst_path = os.path.join(dst_dir, filename)
            shutil.copy(src_path, dst_path)
            print(f'Скопирован: {filename}')

copy_only_ext('documents', 'backup_docs', '.pdf')
Скопирован: report1.pdf
Скопирован: manual.pdf

Копирование с обработкой символических ссылок в директории

Пример python
import shutil
import os

# Создаем структуру для примера (Unix)
if os.name != 'nt':
    os.makedirs('test_dir', exist_ok=True)
    with open('test_dir/real.txt', 'w') as f:
        f.write('content')
    os.symlink('real.txt', 'test_dir/link.txt')
    # Копируем файл, следуя символьным ссылкам
    shutil.copy('test_dir/link.txt', 'copy1.txt', follow_symlinks=True)
    # Копируем как символьную ссылку
    shutil.copy('test_dir/link.txt', 'copy2.txt', follow_symlinks=False)
    print(f'copy1 - это ссылка: {os.path.islink("copy1.txt")}')
    print(f'copy2 - это ссылка: {os.path.islink("copy2.txt")}')
    # Очистка
    os.remove('copy1.txt')
    os.remove('copy2.txt')
    shutil.rmtree('test_dir')
copy1 - это ссылка: False
copy2 - это ссылка: True

питон shutil.copy function comments

En
Shutil.copy Copy file to location