How to copy and move files in Python?

онлайн тренажер по питону
Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Copying and Moving Files in Python: Working with shutil and os Modules

Python development often involves performing operations on files and directories. Creating backups, handling user uploads, organizing project structures, and deploying applications—all these tasks require programmatic management of the file system. Automating such operations significantly simplifies data management and eliminates the need for manual, repetitive actions.

The shutil module in Python provides high-level utilities for working with files and directories. In combination with the os module, it forms a powerful set of cross-platform tools for building flexible file system management scripts. Both modules are part of the Python standard library and are available without any additional installation.

Overview of the shutil Module

The shutil module, named after "shell utility," offers a collection of functions for high-level file and directory operations. The main functions of the module include:

copy() — copies a file without preserving metadata copy2() — copies a file while fully preserving metadata copytree() — recursively copies entire directories move() — moves files and folders to a new location rmtree() — recursively deletes directories and their contents copyfileobj() — copies file-like objects byte by byte

The shutil module integrates effectively with the os module and is suitable for both small automation scripts and large, enterprise-level applications.

File Copying Methods

Basic Copying with shutil.copy()

The shutil.copy() function performs a simple copy of a file's content without transferring its metadata:

import shutil

source = 'source_folder/example.txt'
destination = 'destination_folder/example.txt'
shutil.copy(source, destination)

This function only copies the file's content. The file's metadata, including its creation date, last modification time, and permissions, are not preserved. The function is analogous to the cp command in Unix/Linux systems when used without flags to preserve attributes.

It's important to remember that if the target directory does not exist, an error will occur. It is recommended to check for the existence of the destination directory beforehand or create it programmatically.

Copying with Metadata Preservation: shutil.copy2()

When it is necessary to preserve all information about a file, including timestamps, owner, and permissions, the copy2() function should be used:

shutil.copy2('file.txt', 'backup/file.txt')

This method is particularly useful when creating backups, migrating projects between different systems, or when it is critical to maintain the original attributes of the files. The copy2() function ensures the most accurate reproduction of the source file in the new location.

Copying Directories

Recursive Copying with shutil.copytree()

To copy entire directories with all nested subdirectories and files, the copytree() function is used:

shutil.copytree('old_project', 'new_project')

By default, the copytree() function raises a FileExistsError if the destination directory already exists. Starting with Python 3.8, you can use the dirs_exist_ok=True parameter to allow overwriting or merging the contents:

shutil.copytree('old_project', 'new_project', dirs_exist_ok=True)

The function works recursively and is applied in the following scenarios:

  • Cloning project templates
  • Creating archival copies of large directories
  • Preparing project backups
  • Migrating data between servers

Moving Files and Directories

Using shutil.move()

The move() function facilitates the movement of files and directories from one location to another. It automatically detects the object type and correctly handles both files and directories:

shutil.move('docs/report.pdf', 'archive/report.pdf')

Key features of the move() function:

  • If the destination path is an existing directory, the file is moved inside it, retaining its original name.
  • If a file with an identical name already exists at the destination, it is overwritten without warning.
  • The function supports moving both individual files and entire directories.

Moving directories is done similarly:

shutil.move('project', 'backup/project')

Working with File System Paths

Cross-Platform Path Creation with os.path.join()

Different operating systems use different separator characters for paths. Linux and macOS use a forward slash (/), while Windows uses a backslash (\). The os.path.join() function automatically adapts paths for the current operating system:

import os

folder = 'data'
filename = 'input.csv'
path = os.path.join(folder, filename)
print(path)

The result is automatically adapted to the current operating system. This is critically important when developing cross-platform applications or deploying scripts on various server environments.

Building Complex Paths

The os.path.join() function supports joining multiple path components:

path = os.path.join('projects', 'web_app', 'static', 'css', 'style.css')

This approach ensures code readability and eliminates errors that can occur from manual path construction.

Directory Management

Checking Existence and Creating Directories

Before performing copy or file creation operations, it is necessary to ensure that the target directories exist. The os module provides tools for checking and creating directories:

import os

if not os.path.exists('backup'):
    os.makedirs('backup')

The os.makedirs() function creates all intermediate directories in the specified path if they do not exist. This is particularly useful when creating deeply nested directory structures.

Creating Directories with Error Handling

To improve code reliability, it is recommended to use exception handling:

import os

try:
    os.makedirs('backup/logs/2024', exist_ok=True)
except OSError as error:
    print(f"Error creating directory: {error}")

The exist_ok=True parameter prevents an error from being raised if the directory already exists.

Deletion Operations

Deleting Files

To delete individual files, the os.remove() function is used:

import os
os.remove('old.txt')

This function only deletes files and does not work with directories. Attempting to delete a non-existent file raises a FileNotFoundError exception.

Deleting Directories

To delete directories and their contents, the shutil.rmtree() function is used:

import shutil
shutil.rmtree('old_folder')

Important features of the rmtree() function:

  • Deletion is recursive and irreversible.
  • The function does not require user confirmation.
  • Deleted data is not moved to the trash and cannot be recovered.
  • It is recommended to check the contents of the directories to be deleted beforehand.

Optimizing Operations with Large Files

Using shutil.copyfileobj()

When working with large files, it is recommended to use the copyfileobj() function with buffer size control:

with open('video.mp4', 'rb') as src, open('video_copy.mp4', 'wb') as dst:
    shutil.copyfileobj(src, dst, length=1024*1024)  # 1 MB buffer

The advantages of this approach are:

  • Efficient use of RAM.
  • Ability to configure the buffer size for specific tasks.
  • Suitable for copying files of any size.
  • Provides control over the copying process.

Error Handling and Security

Checking Permissions

Before performing file operations, it is recommended to check access permissions:

import os

if os.access('source_file.txt', os.R_OK):
    if os.access('destination_folder', os.W_OK):
        shutil.copy('source_file.txt', 'destination_folder/')
    else:
        print("No write permissions for the destination directory")
else:
    print("No read permissions for the source file")

Using Context Managers

To ensure that files are properly closed, use context managers:

try:
    with open('source.txt', 'r') as source:
        with open('destination.txt', 'w') as dest:
            dest.write(source.read())
except IOError as e:
    print(f"I/O error: {e}")

Practical Recommendations

Best Practices

When working with file operations, adhere to the following principles:

  • Always use os.path.join() to construct paths.
  • Check for the existence of directories before copying files.
  • Use copytree() for copying large directories.
  • Use copy2() when metadata preservation is necessary.
  • Be aware that move() can overwrite files without warning.
  • Implement logging and exception handling to monitor errors.
  • Test file operations on small data volumes first.

Performance Optimization

To improve performance when working with large volumes of data:

  • Use copyfileobj() with a configured buffer size.
  • Use multithreading for parallel copying of independent files.
  • Consider using libraries like pathlib for a modern approach to path handling.
  • Monitor disk resource usage when copying large files.

Conclusion

The shutil and os modules are fundamental Python tools for file system management. They provide reliable copying, moving, and deletion of files and directories, path management, and directory structure creation and validation. These tools are effectively used in both simple automation scripts and complex enterprise file processing systems.

Using functions like copy, copy2, move, copytree, rmtree, os.path.join, and others allows for the creation of reliable and understandable scripts for managing file structures. These tools are easily extensible and can be integrated into projects of any complexity, ensuring cross-platform compatibility and high performance.

Frequently Asked Questions

How do you copy a file from one folder to another in Python? Use the shutil.copy(source, destination) function for basic copying or shutil.copy2(source, destination) for copying with metadata preservation.

How do you move a file in Python? Use the shutil.move(source, target) function to move files and directories.

What is the difference between copy and copy2? The copy2() function preserves the file's metadata, including creation date, modification time, and permissions, whereas copy() only copies the content.

What does the shutil.copytree() function do? This function recursively copies an entire directory, including all nested subdirectories and files, creating a complete copy of the file structure.

How do you correctly join paths in Python? Use the os.path.join('folder', 'file.txt') function instead of manual string concatenation to ensure cross-platform compatibility.

What should you do if the target directory is missing? Create it using the os.makedirs(path) function, which creates all necessary intermediate directories.

How do you delete a directory with all its contents? Use the shutil.rmtree(path) function, but be mindful that this operation is irreversible and requires prior verification of the contents.

News