Skip to content
beginner

How to Rename Multiple Files with Python

You have a folder full of files with names like photo_2021_01.jpg, IMG_0042.jpg, and final_FINAL_v3.txt. You need them cleaned up, numbered, or renamed to…

Published 2026-09-05Updated 2026-09-1210 min read
Explore the iconic skyline of New York City captured from Brooklyn Bridge, showcasing urban architecture and vibrant city life.
Explore the iconic skyline of New York City captured from Brooklyn Bridge, showcasing urban architecture and vibrant city life. Photo by Vinicius A. Nascimento on Pexels.

You have a folder full of files with names like photo_2021_01.jpg, IMG_0042.jpg, and final_FINAL_v3.txt. You need them cleaned up, numbered, or renamed to something sensible. So you start right-clicking and typing, one slow file at a time.

That works—until you hit file number forty and realize your hand is doing the same boring job over and over. Worse, one typo hides in a name you already moved on from.

Renaming files with Python turns that repetitive chore into a script you can run, check, and reuse. But here's the part most tutorials skip: renaming is destructive. It changes your filesystem, and it's hard to undo. So the real skill isn't just writing a loop—it's previewing your changes before you commit to them.

Let's build that skill with a practical batch rename script.

Why Renaming Files by Hand Is the Wrong Job for You

Think about where messy filenames actually come from. Downloads with names like report (3).pdf. Camera photos exported as DSC_0021.JPG. Project exports with version names that stopped making sense three edits ago. These folders collect over time, and at some point you sit down to fix them.

Doing that by hand costs you twice. First, there's the time: every file is the same click-click-type dance. Second, there's the typo risk: when you rename forty files manually, one wrong keystroke blends into the noise. You won't notice until you need that file and can't find it.

Python fixes both problems. A script renames every file the same way, every time. No fatigue, no drift, no typos from repetition.

But that power cuts both ways. A script will also apply a mistake to every file with the same enthusiasm. That's why the rule for this whole article is simple: preview first, commit second. You print the planned changes, read them like a proofreader, and only then let Python touch your files.

We'll use pathlib for this job. If you've worked with Path objects before, you already have the foundation. If it feels fuzzy, don't worry—the examples below show everything you need.

What You Need Before You Start

You'll need three pieces from your Python toolkit:

  • A Path object pointing at your folder
  • A for loop to walk through the files
  • An f-string to build the new names

Here's the mental model that makes renaming click: a rename is just moving from an old path to a new path inside the same folder. Python isn't doing anything magical. It's saying, "this file used to be called X, now it's called Y."

We'll use Path.rename() rather than the older os.rename() approach. Why? Because pathlib gives you objects that carry their folder information with them. You don't have to juggle separate path strings and hope you joined them correctly. For beginners, that's a big win.

To follow along, create a folder called reports and drop a few files in it with names like these:

notes_draft.txt
notes_final.txt
summary_old.txt
summary_new.txt

Any files work, honestly. The point is to have a small, safe playground before you point a script at real data.

Your First Working Script: Preview the Rename Plan

Let's start with the classic task: turning a folder of randomly named files into clean, numbered names like report_01.txt, report_02.txt, and so on.

Create a file called rename_files.py with this code:

from pathlib import Path

folder = Path("reports")

for index, file in enumerate(folder.iterdir(), start=1):
    new_name = f"report_{index:02d}{file.suffix}"
    new_path = folder / new_name
    print(f"{file.name} -> {new_name}")

Run it from the same directory that contains your reports folder:

python rename_files.py

You'll see output like this:

notes_draft.txt -> report_01.txt
notes_final.txt -> report_02.txt
summary_old.txt -> report_03.txt
summary_new.txt -> report_04.txt

Wait—nothing actually changed. That's the point. This is a dry run: a script that shows you the plan without touching a single file.

Let's unpack what each piece does:

  • folder.iterdir() lists everything inside the folder. Each item is a full Path object, not just a name string.
  • enumerate(..., start=1) gives you a counter that starts at 1 instead of 0.
  • The f-string f"report_{index:02d}{file.suffix}" builds the new name. The :02d part pads the number with a leading zero, so you get 01, 02, up to 99. The file.suffix grabs the original extension like .txt or .jpg, so you don't lose it.
  • folder / new_name joins the folder path and the new filename into one complete path.

Notice that file already knows its own folder. That's the pathlib advantage I mentioned—you never have to manually glue folder paths and filenames together.

Read every line of that output. Does each new name look right? Are there any duplicates? Does the extension survive on every file?

If the plan looks good, you're ready for the commit step.

Knowledge check

Check your understanding

Answer this question before you continue.

What does the first script accomplish when it prints each old and new name but does not call `file.rename()`?
Misconception Check

Focus: Explain why a dry run should precede a destructive batch rename.

Commit: Apply the Rename

A three-step flowchart shows a folder of original filenames becoming a printed rename plan, then a review decision that either returns to editing the naming rule or proceeds to renaming the files. The final step shows the renamed files.
A dry run lets you review every old-to-new filename before the script changes the folder.

Now that you've inspected the plan, it's time to actually rename the files. The commit version looks almost identical—the only difference is one line:

from pathlib import Path

folder = Path("reports")

for index, file in enumerate(folder.iterdir(), start=1):
    new_name = f"report_{index:02d}{file.suffix}"
    new_path = folder / new_name
    file.rename(new_path)
    print(f"{file.name} -> {new_name}")

Run it:

python rename_files.py
notes_draft.txt -> report_01.txt
notes_final.txt -> report_02.txt
summary_old.txt -> report_03.txt
summary_new.txt -> report_04.txt

The file.rename(new_path) line does the actual work. Everything else—building the new name, joining the path—is the same planning logic you already tested.

That two-step rhythm—preview, then commit—is the engineering habit that separates safe scripts from scary ones. Keep it for every destructive script you write, whether you're renaming files, moving folders, or cleaning up old data. It takes five extra seconds and saves you from disasters that take hours.

Tip: When you're testing a rename script, copy a few sample files into a scratch folder first. Practice on the copy. Check the results. Then point the script at your real files.

Knowledge check

Check your understanding

Answer this question before you continue.

Which statement performs the actual rename in the commit version?
Single Choice

Focus: Identify the statement that changes a rename plan into an actual file rename.

Common Mistakes That Break Batch Renames

Even with a preview step, beginners hit the same traps over and over. Here are the four that cause the most damage, with the symptom and fix for each.

The collision trap

Symptom: A file disappears, or Python raises an error about a file already existing.

Cause: You're renaming file_1.txt to file_2.txt, but file_2.txt is already there. Depending on your platform, the original file gets overwritten or the operation fails.

Fix: Check whether the destination exists before renaming, or choose a naming scheme that can't collide. The simple numbered script above is safe when the target names don't already exist in the folder. If you're renaming files that already have names like report_01.txt, pick a different prefix or use a temporary two-step rename. Swapping two filenames without a temporary name is never safe.

The path trap

Symptom: FileNotFoundError even though you can see the file right there.

Cause: You passed a bare filename like "notes.txt" to .rename() instead of the full path. Python looks in the current working directory, not in your target folder.

Fix: Always build the full path. With pathlib, that means using folder / new_name instead of just new_name. If you're iterating with folder.iterdir(), the file object already contains its full path—use it.

Knowledge check

Check your understanding

Answer this question before you continue.

A script iterates through `folder` but raises `FileNotFoundError` because it calls `file.rename(new_name)`. Which replacement follows the article's fix?
Debugging

Focus: Construct the complete destination path needed for a rename inside the target folder.

```python
folder = Path("reports")
new_name = "report_01.txt"
file.rename(???)
```

The extension trap

Symptom: Files end up named report_01.txt.txt or report_01 with no extension.

Cause: You either kept the old extension when building the new name, or you accidentally dropped it.

Fix: Build new names from the file's stem (the name without extension) and add the suffix back explicitly. In our script, file.suffix preserves the extension, and the f-string places it at the end. If you're replacing an extension entirely, use file.with_suffix(".pdf") to swap it cleanly.

The ordering trap

Symptom: Some files rename correctly, then the script fails partway through.

Cause: Your rename sequence collides with itself. For example, renaming a.txt to b.txt when b.txt still needs to become c.txt. The second rename finds b.txt already taken.

Fix: Rename in an order that avoids collisions, or use a two-step approach: first rename everything to temporary names, then rename to the final names. For simple numbering tasks, the straightforward loop works because each destination name is unique.

Renaming Only the Files You Want

Numbering every file in a folder is satisfying, but real life is usually more selective. You need to rename only the .jpg files, or only the files from a certain year, while leaving everything else alone.

The fix is a simple filter. Here's a version that renames only .txt files:

from pathlib import Path

folder = Path("reports")

for index, file in enumerate(folder.glob("*.txt"), start=1):
    new_name = f"notes_{index:02d}{file.suffix}"
    new_path = folder / new_name
    print(f"{file.name} -> {new_name}")

The change is folder.glob("*.txt") instead of folder.iterdir(). The glob() method returns only files matching the pattern, so your loop never sees the other files.

Run the dry-run version first:

python rename_files.py
notes_draft.txt -> notes_01.txt
notes_final.txt -> notes_02.txt

Only the .txt files appear. The .jpg files and everything else stay untouched.

You can filter on more than extensions. Want only files with 2024 in the name? Add a condition inside the loop:

for file in folder.iterdir():
    if "2024" not in file.name:
        continue
    # build the new name and rename

This pattern—iterate, filter, build a new name, preview, commit—covers most batch renaming needs you'll hit as a beginner.

Knowledge check

Check your understanding

Answer this question before you continue.

Given a folder containing `notes_draft.txt`, `photo.jpg`, and `notes_final.txt`, what files appear in the dry-run output when the loop uses `folder.glob("*.txt")`?
Output Prediction

Focus: Predict which files are included when a rename loop uses a filename glob filter.

```python
for index, file in enumerate(folder.glob("*.txt"), start=1):
    new_name = f"notes_{index:02d}{file.suffix}"
    print(f"{file.name} -> {new_name}")
```

When the Simple Version Is Enough (and When It Is Not)

By now you have a working script that renames files safely. You might wonder whether you need something fancier—a GUI tool, a library that watches folders automatically, or a script that handles thousands of files with progress bars.

Here's my judgment: for a controlled folder you can see, the simple pathlib loop is enough. It's readable, it's safe with the preview step, and it handles the folders you actually deal with—your downloads, your exports, your project files.

Fancier tools exist for real reasons. GUI applications help if you rename files constantly and want buttons instead of code. Watchdog-based automation can rename files the moment they appear in a folder. But those are solutions to problems you don't have yet. When you need them, you'll know—because you'll hit a folder that the simple loop can't handle.

Mastering the simple, safe version is the right investment now. It teaches you the mechanism: iterate, filter, build a name, preview, commit. That pattern transfers to moving files, organizing folders, and cleaning up data. The tool changes; the habit doesn't.

Your Next Step: Clean Up a Real Folder

You now have everything you need to rename files with Python safely. The last step is turning this lesson into a habit.

Pick a folder on your computer that actually needs cleaning up. Copy a handful of files into a scratch folder first—never practice on your only copy. Write a script that renames them the way you want. Run the dry-run version and read every line of the plan. Check for collisions, missing extensions, and wrong paths. Then, and only then, swap the print for the real rename and run it.

That rhythm—preview, review, commit—is the skill that makes automation trustworthy. It's the same rhythm you'll use when you move beyond renaming into broader file and folder automation: organizing downloads by type, sorting exports by date, or cleaning up project directories.

Start with one messy folder. Rename it with Python. And give your hand a break from the right-click menu.

Knowledge check

Final check

Finish the article by checking the ideas you just learned.

In the article's numbered naming pattern, what does `file.suffix` contribute to the new name?
Question 1 of 2Single Choice

Focus: Preserve each source file's extension when constructing a numbered destination name.

`new_name = f"report_{index:02d}{file.suffix}"`
Why does the article recommend a temporary two-step rename when swapping names such as `a.txt` and `b.txt`?
Question 2 of 2Misconception Check

Focus: Recognize when a simple rename sequence can collide and when a temporary two-step rename is needed.

References

  1. Build a Bulk File Rename Tool With Python and PyQt – Real Pythonrealpython.com
8sources checked
8source domains
5searches run

Research updated Sep 5, 2026

Practical resource

Want a more structured Python path?

Use the Python Starter Pack to turn scattered tutorials into a focused practice path.

View the bundle
Coming soon

Python Starter Pack

A compact LearnPyFast PDF pack covering what Python is, installation, your first program, running Python code, and Python versions.

$9
PDF BundleTopic PackPythonBeginner
  • 5 curated chapters
  • Enhanced PDF edition with bundle-only learning guidance
  • Offline-friendly format for focused review
  • Source article links for future online updates

Coming soon

Free Python bundle

Get the LearnPyFast Python Starter Bundle

A focused collection of beginner-friendly Python resources to help you move from setup to building practical projects.

You’ll receive the bundle by email. You can unsubscribe anytime.

No spam. You can unsubscribe anytime. See our Privacy policy.

Related sites

Continue beyond Python

Explore related Worldmonger sites when you want to move from Python basics into JavaScript or LLM application building.

JavaScript tutorialstutorial

LearnJSFast

Beginner-friendly JavaScript tutorials for practical web development and self-taught developers.

JavaScriptFrontendWeb development
Visit LearnJSFast
LLM tutorialstutorial

LearnLLMFast

Practical LLM tutorials for builders who want to understand prompting, workflows, agents, and AI applications.

LLMAIBuilders
Visit LearnLLMFast

Keep learning

Related tutorials

Continue with nearby Python topics and beginner-friendly explanations.

Captivating view of a stormy sea under dark clouds, showcasing powerful ocean waves.
beginner
6 min read

Beginner Python Project Ideas

You finished the syntax tutorials. You know what a loop does, you can write a function, and you understand what a dictionary is for. Then you close the…

Read tutorial