How to Rename Hundreds of Files in Seconds with Python

· 9 min read

Introduction

Renaming files is one of the most common automation tasks in everyday computer work. It sounds simple until you need to rename 300 photos, clean up downloaded files, or standardize messy filenames from different sources.

Typical situations include:

  • Cleaning up chaotic filenames in a Downloads folder
  • Adding date prefixes to invoices or reports
  • Replacing spaces with underscores
  • Removing unwanted characters from filenames
  • Renaming exported screenshots or camera images

Doing this manually is slow and error-prone. With Python, you can rename hundreds of files in seconds using only a few lines of code.

In this tutorial, you will learn how to:

  • Rename a single file
  • Rename all files in a folder
  • Add prefixes and suffixes
  • Replace characters in filenames
  • Apply custom batch renaming rules
  • Avoid dangerous mistakes when working with real files

All examples are tested on Python 3.12.


Two Ways to Rename: os vs pathlib

Python provides two common ways to rename files:

MethodStyle
os.rename()Traditional and straightforward
pathlib.Path.rename()Modern and easier to read

Using os.rename()

import os

os.rename("old.txt", "new.txt")

Using pathlib

from pathlib import Path

Path("old.txt").rename("new.txt")

Both approaches work well. The main difference is readability and convenience. This tutorial mainly uses pathlib because it provides cleaner syntax and better path handling. You will still see equivalent os examples when useful.


Renaming a Single File

Let’s start with the simplest case: renaming one file.

Suppose your project folder contains:

report.txt

You want to rename it to:

monthly_report.txt

Basic Example

from pathlib import Path

old_file = Path("report.txt")

new_file = Path("monthly_report.txt")

old_file.rename(new_file)

print("File renamed successfully")

Expected output:

File renamed successfully

This code renames the file in the current working directory.


Relative vs Absolute Paths

You can use either relative or absolute paths.

Relative path — refers to a file in the current working directory:

Path("report.txt")

Absolute path — works regardless of where the script runs from:

Path("C:/Users/Alex/Documents/report.txt")

Absolute paths are safer when scripts may be run from different locations.


What Happens If the Target Already Exists?

Behavior depends on the operating system. On some systems, renaming may overwrite the destination file. On others, it may raise an error.

Safer approach:

from pathlib import Path

source = Path("report.txt")
target = Path("monthly_report.txt")

if target.exists():
    print("Target file already exists")
else:
    source.rename(target)

Always check before renaming important files.


Renaming All Files in a Folder

Batch renaming becomes much more useful when processing entire directories.


Example 1: Rename All .txt Files to .md

Suppose a folder contains:

notes.txt
tasks.txt
ideas.txt

You want to convert them into Markdown filenames.

from pathlib import Path

folder = Path("documents")

for file in folder.glob("*.txt"):

    new_name = file.with_suffix(".md")

    file.rename(new_name)

    print(f"{file.name} -> {new_name.name}")

Expected output:

notes.txt -> notes.md
tasks.txt -> tasks.md
ideas.txt -> ideas.md

glob("*.txt") filters only .txt files.


Example 2: Add IMG_ Prefix to Photos

Suppose your folder contains:

beach.jpg
sunset.jpg
family.jpg

You want camera-style filenames:

IMG_beach.jpg
IMG_sunset.jpg
IMG_family.jpg

Script:

from pathlib import Path

folder = Path("photos")

for file in folder.glob("*.jpg"):

    new_name = file.with_name(f"IMG_{file.name}")

    file.rename(new_name)

    print(f"Renamed: {new_name.name}")

Expected output:

Renamed: IMG_beach.jpg
Renamed: IMG_sunset.jpg
Renamed: IMG_family.jpg

This pattern is common when organizing exported images or phone backups.


iterdir() vs glob() vs rglob()

These three methods iterate through files but behave differently.

MethodBehaviorWhen to Use
iterdir()All files and subdirectories in current folderSimple traversal, no filter needed
glob("*.jpg")Files matching a pattern in current folderFilter by extension or name
rglob("*.jpg")Files matching a pattern in ALL subfoldersRecursive search

In most batch renaming scripts, glob() is the most convenient option. rglob() becomes useful when files are spread across nested directories.


Common Real-World Patterns

Here are several renaming patterns that appear frequently in real automation tasks.

Pattern 1: Add a Date Prefix

Original files:

invoice.pdf
report.docx

Desired result:

2026-05-15_invoice.pdf
2026-05-15_report.docx

Script:

from pathlib import Path
from datetime import date

folder = Path("documents")

today = date.today().isoformat()

for file in folder.iterdir():

    if file.is_file():

        new_name = f"{today}_{file.name}"

        file.rename(file.with_name(new_name))

        print(new_name)

Expected output:

2026-05-15_invoice.pdf
2026-05-15_report.docx

This is useful for reports, backups, invoices, and exported datasets.


Pattern 2: Replace Spaces with Underscores

Original files:

My File.pdf
Sales Report.xlsx

Desired result:

My_File.pdf
Sales_Report.xlsx

Script:

from pathlib import Path

folder = Path("downloads")

for file in folder.iterdir():

    if file.is_file():

        clean_name = file.name.replace(" ", "_")

        file.rename(file.with_name(clean_name))

        print(clean_name)

Expected output:

My_File.pdf
Sales_Report.xlsx

Replacing spaces is especially useful for web uploads, scripts, and command-line compatibility.


Pattern 3: Rename Files Sequentially

Original files:

photo.jpg
image.jpg
pic.jpg

Desired result:

001.jpg
002.jpg
003.jpg

Script:

from pathlib import Path

folder = Path("images")

files = list(folder.glob("*.jpg"))

for index, file in enumerate(files, start=1):

    new_name = f"{index:03}.jpg"

    file.rename(file.with_name(new_name))

    print(f"{file.name} -> {new_name}")

Expected output:

photo.jpg -> 001.jpg
image.jpg -> 002.jpg
pic.jpg -> 003.jpg

{index:03} pads numbers with zeros.


Pattern 4: Remove Specific Characters

Original files:

file(1).txt
notes(backup).txt

Desired result:

file1.txt
notesbackup.txt

Script:

from pathlib import Path

folder = Path("files")

for file in folder.iterdir():

    if file.is_file():

        clean_name = (
            file.name
            .replace("(", "")
            .replace(")", "")
        )

        file.rename(file.with_name(clean_name))

        print(clean_name)

Expected output:

file1.txt
notesbackup.txt

This is useful when cleaning filenames exported by browsers or cloud storage systems. The is_file() check prevents accidentally renaming folders whose names also contain those characters.


Pattern 5: Change File Extensions

Original files:

photo1.jpeg
photo2.jpeg

Desired result:

photo1.jpg
photo2.jpg

Script:

from pathlib import Path

folder = Path("photos")

for file in folder.glob("*.jpeg"):

    new_file = file.with_suffix(".jpg")

    file.rename(new_file)

    print(new_file.name)

Expected output:

photo1.jpg
photo2.jpg

Changing extensions is common when standardizing media libraries.


Pattern 6: Convert All Filenames to Lowercase

Useful when consistency matters — for example, before deploying assets to a web server, or when filenames mix uppercase and lowercase from different sources.

Original files:

README.md
Photo.JPG
DATA.csv

Desired result:

readme.md
photo.jpg
data.csv

Script:

from pathlib import Path

folder = Path("project")

for file in folder.iterdir():

    if file.is_file():

        new_name = file.name.lower()

        if new_name != file.name:
            file.rename(file.with_name(new_name))
            print(f"{file.name} -> {new_name}")

Expected output:

README.md -> readme.md
Photo.JPG -> photo.jpg
DATA.csv -> data.csv

The if new_name != file.name check skips files that are already lowercase, which avoids unnecessary rename operations.


Safety Tips: Don’t Lose Your Files

File renaming scripts can accidentally damage large directories very quickly. A small bug can rename thousands of files incorrectly in seconds. Here are some important safety practices.


Always Start with a Dry Run

Instead of renaming immediately, print the planned changes first.

Risky:

file.rename(new_name)

Safer:

print(f"{file.name} -> {new_name.name}")

Verify the output before making actual changes.


Test on a Copy Folder First

Never test directly on:

  • Work documents
  • Family photos
  • Production backups

Create a duplicate test folder first.


Avoid Overwriting Existing Files

Always check whether the destination already exists.

if not new_path.exists():
    file.rename(new_path)

Otherwise, files may be replaced accidentally.


Avoid Cloud Sync Folders

Be careful with:

  • OneDrive
  • iCloud Drive
  • Google Drive
  • Dropbox

Running aggressive rename scripts inside synced folders can create sync conflicts or duplicate files.


Add a Confirmation Prompt

Simple confirmation prompts prevent many mistakes.


Example: Safe Batch Rename Script

from pathlib import Path

folder = Path("downloads")

planned_changes = []

for file in folder.glob("*.txt"):

    new_name = file.with_name(
        file.stem.replace(" ", "_") + file.suffix
    )

    planned_changes.append((file, new_name))

print("Planned changes:")

for old, new in planned_changes:
    print(f"{old.name} -> {new.name}")

confirm = input("Continue? (y/n): ")

if confirm.lower() == "y":

    for old, new in planned_changes:

        try:

            if new.exists():
                print(f"Skipped (exists): {new.name}")
                continue

            old.rename(new)

            print(f"Renamed: {new.name}")

        except Exception as e:
            print(f"Error: {e}")

else:
    print("Operation cancelled")

This script includes:

  • Dry-run preview
  • Confirmation prompt
  • File existence checks
  • Exception handling

These practices matter when working with real data.


Renaming Files Recursively (Including Subfolders)

Sometimes files are spread across nested folders. Path.rglob() searches recursively through all subdirectories.


Example: Clean Up System Junk Files

Some operating systems create hidden files that clutter your project folders — macOS creates .DS_Store, and Windows creates Thumbs.db and desktop.ini. This script finds and removes them across an entire project directory.

First, do a dry-run to see what will be deleted:

from pathlib import Path

project = Path("my_project")

patterns = [".DS_Store", "Thumbs.db", "desktop.ini"]

for pattern in patterns:
    for file in project.rglob(pattern):
        print(file)

After verifying the list looks correct, run the deletion:

from pathlib import Path

project = Path("my_project")

patterns = [".DS_Store", "Thumbs.db", "desktop.ini"]

for pattern in patterns:
    for file in project.rglob(pattern):
        file.unlink()
        print(f"Deleted: {file}")

Expected output:

Deleted: my_project/assets/.DS_Store
Deleted: my_project/docs/Thumbs.db

Recursive operations are powerful but dangerous. Always dry-run first.


Beyond Renaming: Pathlib for File Management

pathlib is useful far beyond renaming. It can also:

  • Create directories
  • Delete files
  • Move files
  • Read file metadata (size, modification time)
  • Traverse folders

Example: read file metadata.

from pathlib import Path
from datetime import datetime

file = Path("report.pdf")

size_kb = file.stat().st_size / 1024
modified = datetime.fromtimestamp(file.stat().st_mtime)

print(f"Size: {size_kb:.1f} KB")
print(f"Modified: {modified}")

Expected output:

Size: 200.0 KB
Modified: 2026-05-15 14:23:01

You can build complete file management automation pipelines using only Python’s standard library.


Wrap-Up

Python makes large-scale file renaming surprisingly simple. With pathlib, you can clean filenames, organize photos, standardize extensions, and automate repetitive folder management tasks with very little code.

The most important habit is safety: always start with a dry-run before performing actual renames.

Try these examples on a test folder first, then adapt them to your own workflow. For questions or future automation topics, get in touch via the Contact page.

You may also be interested in automating email delivery with Python, which pairs well with file renaming scripts — for example, automatically renaming a generated report and emailing it to a team.