
Batch-Rename Files by Pattern with a Windows Batch Script
Before you run this
This is a cmd.exe batch file that renames files in one folder by find-and-replace: it takes every file matching a mask (say *.txt), swaps a substring in the filename (say draft → final), and renames it. Its purpose is bulk cleanup of filenames — removing a stray word, fixing a prefix, changing a spelling — without you clicking through Explorer.
- Privileges: No administrator rights are needed as long as you own the files and the folder isn't a protected system location. Renaming files under
C:\Windows,C:\Program Files, or another user's profile would need an elevated prompt, and you should not be doing that anyway. Run it as your normal user. - Test first: Read the script before you run it. Point it at a copy of a folder — not the real one — the first time. The version below ships with a dry-run switch turned on by default, so it prints what it would rename and touches nothing until you deliberately flip it off. Use that.
- This changes data, and there is no automatic undo. A batch
rendoes not go into the Explorer "Undo" history — pressing Ctrl+Z in a window later will not reverse it. The rename is done when it's done. It is reversible by hand only if the change is clean (see the Undo section), so treat the first real run with the same care you'd give any bulk operation. - Collisions:
renwill not silently overwrite an existing file — if the target name already exists it errors out. The script checks for that and skips, rather than clobbering. Substring matching in cmd is case-insensitive, soDraft,draft, andDRAFTall match; know that going in.
Assumed environment: Windows 10 or Windows 11, run from cmd.exe (the classic Command Prompt), operating on a single folder, non-recursively. If you'd rather do this in PowerShell, the standard path there is Get-ChildItem piped to Rename-Item -WhatIf — that's a different guide; I'm doing the batch-file way here.
The simplest case: change an extension
If all you want is to change the extension on a batch of files, you don't need a script at all. The built-in ren command takes wildcards:
ren *.jpeg *.jpg
That renames every .jpeg in the current directory to .jpg. It's the right tool when the pattern is a clean extension swap. It gets unreliable the moment you try to do partial-name surgery with wildcards, though — cmd's wildcard rename has genuinely surprising edge behaviour. For anything more than an extension change, use the loop below.
The script: find-and-replace in filenames
Save this as rename-pattern.bat. Edit the five variables at the top, then run it.
@echo off
setlocal enabledelayedexpansion
rem === Settings you edit ===
set "TARGETDIR=C:\path\to\files"
set "FILEMASK=*.txt"
set "FIND=draft"
set "REPLACE=final"
set "DRYRUN=1" rem 1 = preview only, 0 = actually rename
rem === Do not edit below this line ===
pushd "%TARGETDIR%" || (echo Cannot open "%TARGETDIR%" & exit /b 1)
for %%F in (%FILEMASK%) do (
set "OLD=%%~nxF"
rem substring replace: !OLD! with FIND swapped for REPLACE
set "NEW=!OLD:%FIND%=%REPLACE%!"
if not "!OLD!"=="!NEW!" (
if "%DRYRUN%"=="1" (
echo [DRY RUN] "!OLD!" --^> "!NEW!"
) else if exist "!NEW!" (
echo SKIP : "!NEW!" already exists, leaving "!OLD!" alone
) else (
ren "!OLD!" "!NEW!"
echo RENAMED : "!OLD!" --^> "!NEW!"
)
)
)
popd
endlocal
What the non-obvious lines do:
setlocal enabledelayedexpansionlets me read a variable I just set inside the same loop iteration, using!OLD!instead of%OLD%. Without it, the loop would use the value from before the loop started — a classic cmd trap.%%~nxFis the file's name plus extension with any path stripped. In a batch file the loop variable takes%%F; on the command line directly it would be%F.set "NEW=!OLD:%FIND%=%REPLACE%!"is the substitution. cmd's%var:old=new%replaces every occurrence ofoldin the string, not just the first. SoFIND=a,REPLACE=bonbananagivesbbnbnb. Keep yourFINDstring specific.- The
if not "!OLD!"=="!NEW!"guard means files that don't contain the pattern are ignored, so the output only lists what actually changed. pushd/popdmove into and back out of the target folder sorenoperates there.rencannot move a file between folders — it renames in place only.
Run it
Open Command Prompt, cd to wherever you saved it, and:
rename-pattern.bat
With DRYRUN=1 it prints lines like:
[DRY RUN] "q1-draft-report.txt" --> "q1-final-report.txt"
[DRY RUN] "draft-notes.txt" --> "final-notes.txt"
Read that list. If — and only if — every proposed rename is correct, edit the file, set DRYRUN=0, and run it again to commit.
Common variations
- Add or remove a prefix: to strip a leading
IMG_, setFIND=IMG_andREPLACE=(empty). To add a prefix you can't do it with this replace logic; you'd rename toPREFIX_!OLD!instead — that's a one-line change to therenline,ren "!OLD!" "PREFIX_!OLD!", but test it on a copy because it has its own collision cases. - Recurse into subfolders: swap the loop for
for /r "%TARGETDIR%" %%F in (%FILEMASK%) do (...)and useren "%%F" "!NEW!"with the full path. Recursion multiplies the blast radius, so dry-run it hard. - Case sensitivity: cmd's substring replace is case-insensitive and there's no switch to change that. If you need case-sensitive matching, this isn't the right tool — do it in PowerShell.
Verify it worked
List the folder and confirm the names are what you expect:
dir /b "C:\path\to\files"
/b gives bare filenames, one per line, which is easy to eyeball or pipe into a file for a before/after comparison:
dir /b "C:\path\to\files" > after.txt
If you captured a dir /b > before.txt beforehand, fc before.txt after.txt shows exactly what changed.
Undo
There is no automatic rollback. If the change was clean — a simple, unique substring swap with no skipped collisions — you can reverse it by running the same script with FIND and REPLACE swapped. For the example above, set FIND=final and REPLACE=draft, dry-run it, and confirm before committing.
That reversal is only safe when nothing was skipped and the replacement string didn't already occur in the original names. If the output during the real run showed any SKIP lines, or the pattern was ambiguous, do not trust a blind reverse — restore those files from your copy or backup instead. This is exactly why the first run should be against a copy of the folder.
For the official reference on ren, for, and variable substring substitution, see the Windows Commands documentation on Microsoft Learn (search "ren command" and "for command").
Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.
More about the author →Was this article helpful?
Tap a star — no sign-in needed.
Be the first to rate this article.
