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
- How to Use os.mkdir in Python
- Python: Using os.listdir to List Files in a Directory
- How to Use os.getenv in Python
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.