Python Script for Bulk File Renaming and Organization
Core Concepts and Safety Precautions
Automating file operations requires careful execution. Before running any script that modifies files, it is crucial to:- **Backup Critical Data:** Always create a full backup of the directory you intend to modify.
- **Dry Run:** Implement a "dry run" mode in your script first, printing what *would* happen without actually making changes. This helps verify logic.
- **Test on Dummy Data:** Test the script on a separate directory with non-essential dummy files.
Script 1: Bulk Renaming Files
This script demonstrates how to rename files by adding a prefix and sequential numbering. This pattern can be adapted for date-based renaming, replacing substrings, or other custom logic.
import os
def rename_files_bulk(directory_path, prefix="file_", dry_run=True):
"""
Renames files in a given directory with a specified prefix and sequential numbering.
Args:
directory_path (str): The path to the directory containing the files.
prefix (str): The prefix to add to each filename.
dry_run (bool): If True, prints changes without executing. If False, performs changes.
"""
if not os.path.isdir(directory_path):
print(f"Error: Directory not found at {directory_path}")
return
files = [f for f in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, f))]
files.sort() # Ensure consistent ordering
print(f"--- {'DRY RUN' if dry_run else 'EXECUTING'} RENAMING OPERATION ---")
for i, filename in enumerate(files):
name, ext = os.path.splitext(filename)
new_filename = f"{prefix}{i+1:03d}{ext}" # e.g., file_001.txt
old_path = os.path.join(directory_path, filename)
new_path = os.path.join(directory_path, new_filename)
print(f"Renaming: '{filename}' -> '{new_filename}'")
if not dry_run:
try:
os.rename(old_path, new_path)
except OSError as e:
print(f"Error renaming {filename}: {e}")
print("Renaming operation complete.")
# --- Configuration ---
# Set your target directory here
target_directory = 'C:/Users/YourUser/Documents/MyUnorganizedFiles'
# For Linux/macOS: '/home/youruser/MyUnorganizedFiles'
# Example Usage:
# Run in dry-run mode first to see what changes will be made
rename_files_bulk(target_directory, prefix="ProjectX_Doc_", dry_run=True)
# After verifying, change dry_run to False to execute
# rename_files_bulk(target_directory, prefix="ProjectX_Doc_", dry_run=False)
To modify renaming logic, adjust the `new_filename` generation. For instance, to replace spaces with underscores: `new_filename = name.replace(' ', '_') + ext`. For date-based renaming, you might parse the file's modification time using `os.path.getmtime()` and `datetime.fromtimestamp()`.
Script 2: Bulk File Organization (Moving to Subdirectories)
This script organizes files by moving them into subdirectories based on their file extension. This approach can be extended to organize by date, file size, or patterns in the filename.
import os
import shutil
import datetime
def organize_files_bulk(directory_path, organize_by='extension', dry_run=True):
"""
Organizes files in a directory into subdirectories based on specified criteria.
Args:
directory_path (str): The path to the directory to organize.
organize_by (str): Criteria for organization ('extension', 'year', 'month').
dry_run (bool): If True, prints changes without executing. If False, performs changes.
"""
if not os.path.isdir(directory_path):
print(f"Error: Directory not found at {directory_path}")
return
print(f"--- {'DRY RUN' if dry_run else 'EXECUTING'} ORGANIZATION OPERATION ---")
for filename in os.listdir(directory_path):
old_path = os.path.join(directory_path, filename)
if os.path.isfile(old_path):
name, ext = os.path.splitext(filename)
target_subdir_name = ""
if organize_by == 'extension':
target_subdir_name = ext[1:].lower() if ext else "no_extension"
elif organize_by == 'year':
mod_time = os.path.getmtime(old_path)
dt_object = datetime.datetime.fromtimestamp(mod_time)
target_subdir_name = str(dt_object.year)
elif organize_by == 'month':
mod_time = os.path.getmtime(old_path)
dt_object = datetime.datetime.fromtimestamp(mod_time)
target_subdir_name = dt_object.strftime("%Y-%m")
else:
print(f"Warning: Unsupported organization criteria '{organize_by}' for {filename}. Skipping.")
continue
target_dir = os.path.join(directory_path, target_subdir_name)
new_path = os.path.join(target_dir, filename)
print(f"Moving: '{filename}' -> '{target_subdir_name}/{filename}'")
if not dry_run:
try:
os.makedirs(target_dir, exist_ok=True) # Create subdir if it doesn't exist
shutil.move(old_path, new_path)
except OSError as e:
print(f"Error moving {filename}: {e}")
print("Organization operation complete.")
# --- Configuration ---
# Set your target directory here
target_directory = 'C:/Users/YourUser/Documents/MyUnorganizedFiles'
# For Linux/macOS: '/home/youruser/MyUnorganizedFiles'
# Example Usage:
# Run in dry-run mode first
organize_files_bulk(target_directory, organize_by='extension', dry_run=True)
# organize_files_bulk(target_directory, organize_by='year', dry_run=True)
# After verifying, change dry_run to False to execute
# organize_files_bulk(target_directory, organize_by='extension', dry_run=False)
To organize by other criteria, modify the `target_subdir_name` generation logic. For example, to organize by the first letter of the filename, you could use `target_subdir_name = name[0].upper()`.
Combining Renaming and Organization
The renaming and organization logic can be combined within a single loop. First, determine the new filename, then determine the target subdirectory, create it if necessary, and finally move the file with its new name. Always prioritize the dry run approach to prevent unintended modifications.Need this done fast? order it on Kwork.
Need help with this?
I take on freelance fixes and builds in this area.