Last modified: Oct 16, 2024 By Alexander Williams

How to Copy Files in Python: Complete Guide

Introduction

In Python, there are multiple ways to copy files. The most common methods use the shutil module, which provides high-level operations on files. This module is preferred over the os module for file copying operations.

Basic File Copying

Here's how to perform basic file copying using shutil.copy() and shutil.copy2():


import shutil
import os

# Basic copy - copies content and mode bits
shutil.copy('source.txt', 'destination.txt')

# Copy with metadata - preserves all metadata
shutil.copy2('source.txt', 'destination.txt')

# Copy to a directory
shutil.copy('source.txt', 'backup_folder')

Error Handling

Here's how to handle common copying scenarios with proper error handling:


import shutil
import os
from datetime import datetime

def safe_copy_file(source, destination):
    """Safely copy a file with error handling"""
    try:
        # Create destination directory if it doesn't exist
        os.makedirs(os.path.dirname(destination), exist_ok=True)
        
        # Copy the file
        shutil.copy2(source, destination)
        print(f"Successfully copied {source} to {destination}")
        return True
    except FileNotFoundError:
        print(f"Source file not found: {source}")
        return False
    except PermissionError:
        print(f"Permission denied: Cannot copy {source}")
        return False
    except shutil.SameFileError:
        print(f"Source and destination are the same file")
        return False
    except OSError as e:
        print(f"Error copying file: {e}")
        return False

# Example usage
safe_copy_file('data.txt', 'backup/data.txt')

Copying with Backup

Here's how to create backup copies of files:


import shutil
import os
from datetime import datetime

def copy_with_backup(source, destination):
    """Copy file and create backup if destination exists"""
    if os.path.exists(destination):
        # Create backup name with timestamp
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        backup_name = f"{destination}.{timestamp}.bak"
        
        # Backup existing file
        shutil.copy2(destination, backup_name)
        print(f"Created backup: {backup_name}")
    
    # Copy new file
    shutil.copy2(source, destination)
    print(f"Copied {source} to {destination}")

# Example usage
copy_with_backup('config.ini', 'config.ini.new')

Copying Multiple Files

Here's how to copy multiple files efficiently:


import shutil
import os
import glob

def copy_multiple_files(source_pattern, destination_dir):
    """Copy multiple files matching a pattern"""
    # Ensure destination directory exists
    os.makedirs(destination_dir, exist_ok=True)
    
    # Get list of files matching pattern
    source_files = glob.glob(source_pattern)
    
    results = {
        'success': [],
        'failed': []
    }
    
    for source in source_files:
        try:
            destination = os.path.join(destination_dir, os.path.basename(source))
            shutil.copy2(source, destination)
            results['success'].append(source)
        except Exception as e:
            results['failed'].append({'file': source, 'error': str(e)})
    
    return results

# Example usage
results = copy_multiple_files('*.txt', 'backup_folder')
print(f"Successfully copied: {len(results['success'])} files")
print(f"Failed to copy: {len(results['failed'])} files")

Advanced Copying Techniques

Here are some advanced copying scenarios:


import shutil
import os
import hashlib

class FileCopyManager:
    def __init__(self, source_dir, dest_dir):
        self.source_dir = source_dir
        self.dest_dir = dest_dir
    
    def get_file_hash(self, filepath):
        """Calculate MD5 hash of file"""
        hash_md5 = hashlib.md5()
        with open(filepath, "rb") as f:
            for chunk in iter(lambda: f.read(4096), b""):
                hash_md5.update(chunk)
        return hash_md5.hexdigest()
    
    def copy_if_different(self, filename):
        """Copy file only if content is different"""
        source = os.path.join(self.source_dir, filename)
        dest = os.path.join(self.dest_dir, filename)
        
        if not os.path.exists(dest):
            shutil.copy2(source, dest)
            return True
            
        if self.get_file_hash(source) != self.get_file_hash(dest):
            shutil.copy2(source, dest)
            return True
            
        return False

# Example usage
manager = FileCopyManager('source_folder', 'dest_folder')
updated = manager.copy_if_different('data.txt')
if updated:
    print("File was copied due to changes")
else:
    print("File unchanged, no copy needed")

Best Practices

  • Use shutil.copy2() instead of shutil.copy() to preserve metadata
  • Always check for existing files before copying
  • Implement proper error handling
  • Create backup copies of important files
  • Verify file integrity after copying when needed

Common Pitfalls

Here are some situations to watch out for:


import shutil
import os

# Don't use with files that are being modified
def unsafe_copy():
    shutil.copy('actively_modified.txt', 'destination.txt')

# Safe version - check if file is locked
def safe_copy(source, destination):
    try:
        with open(source, 'rb') as f:
            # Try to get a lock on the file
            pass
        shutil.copy2(source, destination)
        return True
    except (IOError, OSError):
        print("File is in use or locked")
        return False

# Handle permission issues
def copy_with_permissions(source, destination):
    try:
        shutil.copy2(source, destination)
        # Ensure readable permissions
        os.chmod(destination, 0o644)
    except PermissionError:
        print("Permission denied")

Related Articles

Conclusion

Python provides multiple ways to copy files, with shutil being the preferred module for such operations. Remember to handle errors appropriately, create backups when necessary, and follow best practices for secure and reliable file copying. The shutil.copy2() function is typically the best choice as it preserves all metadata of the original file.