ZetCode

Python os.renames Function

Last modified April 11, 2025

This comprehensive guide explores Python's os.renames function, which recursively renames files and directories. We'll cover basic usage, error handling, and practical file system manipulation examples.

Basic Definitions

The os.renames function recursively renames a file or directory. It creates any necessary intermediate directories and removes empty ones.

Key parameters: old (current path), new (desired path). Works across platforms but behavior may differ between Unix and Windows systems.

Basic File Renaming

The simplest use of os.renames renames a single file. This example demonstrates basic file renaming with error handling.

basic_rename.py
import os

# Create a test file
with open("old_file.txt", "w") as f:
    f.write("Test content")

# Rename the file
try:
    os.renames("old_file.txt", "new_file.txt")
    print("File renamed successfully")
except OSError as e:
    print(f"Error renaming file: {e}")

# Verify the rename
if os.path.exists("new_file.txt"):
    print("New file exists")
if not os.path.exists("old_file.txt"):
    print("Old file removed")

This example creates a file, renames it, and verifies the operation. The try-except block handles potential errors like permission issues.

Note that os.renames will overwrite existing files on Unix but may fail on Windows if the destination exists.

Directory Renaming

os.renames can rename entire directories, including their contents. This example shows directory renaming with subdirectories.

directory_rename.py
import os

# Create directory structure
os.makedirs("old_dir/subdir", exist_ok=True)
with open("old_dir/file1.txt", "w") as f:
    f.write("File 1")
with open("old_dir/subdir/file2.txt", "w") as f:
    f.write("File 2")

# Rename the directory
os.renames("old_dir", "new_dir")

# Verify the rename
print("Contents of new_dir:")
for root, dirs, files in os.walk("new_dir"):
    print(f"Directory: {root}")
    for file in files:
        print(f"  File: {file}")

This creates a directory with subdirectory and files, then renames the top-level directory. The os.walk call verifies all contents were moved.

The function maintains the entire directory structure during the rename operation.

Moving Files Between Directories

os.renames can move files between directories, creating destination directories if needed. This example demonstrates file movement.

move_file.py
import os

# Create source file
os.makedirs("source_dir", exist_ok=True)
with open("source_dir/file.txt", "w") as f:
    f.write("Test content")

# Move to non-existent destination
os.renames("source_dir/file.txt", "dest_dir/file.txt")

# Verify the move
print(f"Source exists: {os.path.exists('source_dir/file.txt')}")
print(f"Destination exists: {os.path.exists('dest_dir/file.txt')}")
print(f"Source directory empty: {not os.listdir('source_dir')}")

This moves a file from source_dir to a new dest_dir, which is automatically created. The source directory becomes empty after the move.

If the source directory becomes empty after the move, os.renames will remove it as part of the operation.

Handling Errors

This example demonstrates proper error handling when using os.renames, including common failure scenarios.

error_handling.py
import os

def safe_rename(old, new):
    try:
        os.renames(old, new)
        print(f"Successfully renamed {old} to {new}")
    except FileNotFoundError:
        print(f"Source path {old} does not exist")
    except PermissionError:
        print(f"Permission denied for {old} or {new}")
    except OSError as e:
        print(f"Error renaming {old} to {new}: {e}")

# Test cases
safe_rename("nonexistent.txt", "new.txt")  # FileNotFound
safe_rename("/root/file.txt", "new.txt")   # PermissionError (Unix)
safe_rename("locked_file.txt", "new.txt")  # PermissionError (Windows)
safe_rename("valid.txt", "/invalid/path/new.txt")  # OSError

The safe_rename function wraps os.renames with comprehensive error handling. Different exceptions are caught and handled appropriately.

This approach is more robust than letting exceptions propagate, especially in user-facing applications.

Cross-Device Renaming

When source and destination are on different devices, os.renames may fail. This example shows how to handle such cases.

cross_device.py
import os
import shutil

def cross_device_rename(old, new):
    try:
        os.renames(old, new)
    except OSError as e:
        if "Invalid cross-device link" in str(e):
            print("Cross-device operation detected")
            print("Falling back to copy + delete")
            shutil.move(old, new)  # Uses copy+delete internally
        else:
            raise

# Test (may need actual different devices to trigger)
cross_device_rename("/tmp/file.txt", "/mnt/other_device/file.txt")

This demonstrates handling cross-device rename limitations by falling back to shutil.move, which copies then deletes the source.

The shutil.move function is more flexible for cross-device operations but may be slower for large files.

Recursive Directory Restructuring

os.renames excels at complex directory restructuring. This example shows moving files while changing directory hierarchy.

restructure.py
import os

# Create complex structure
os.makedirs("project/docs/images", exist_ok=True)
os.makedirs("project/src/modules", exist_ok=True)
with open("project/docs/readme.txt", "w") as f:
    f.write("Documentation")
with open("project/src/main.py", "w") as f:
    f.write("print('Hello')")

# Restructure the project
os.renames("project/docs", "new_project/documentation")
os.renames("project/src", "new_project/source_code")

# Verify new structure
print("New project structure:")
for root, dirs, files in os.walk("new_project"):
    print(root)
    for name in files:
        print(f"  {name}")

This restructures a project directory, moving docs to documentation and src to source_code. Empty directories are automatically cleaned up.

The operation maintains all file contents while changing the directory hierarchy in a single call.

Atomicity Considerations

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.