What a Batch Script Is Good At (and What It Can't See)
A batch script, a plain text file saved with a .bat extension, is just a list of cmd.exe commands that run top to bottom when you double-click it. For renaming files, that's a surprisingly capable little tool. If your job is uniform, add a prefix, change an extension, number a sequence, strip a common chunk of text, a handful of lines gets it done, and you keep the file forever to run again next month.
The honest boundary is this: a batch script works on filenames, not on file contents. It matches names by pattern and rewrites them by pattern. It never opens the file, never reads the text on the page, never knows that scan_0007.pdf is an Acme invoice dated the 14th. If the new name you want is already sitting in the old name, cmd can rearrange it. If the new name lives inside the document, cmd cannot reach it. Keep that line in mind and everything below fits into place.
The rest of this guide builds up in order: the ren command for simple renames, FOR loops for doing it across many files with a counter, saving and scheduling the result, and finally a clear map of where cmd stops and you need PowerShell or a content-aware tool instead.
Rename Files With the ren Command
The foundation of any rename batch script is the ren command (rename works identically, it's the same command). At its simplest, ren oldname.txt newname.txt renames one file. The syntax is always ren <what to match> <what to make it>.
Where ren earns its keep is wildcards. The asterisk stands in for any run of characters, and the question mark for a single character. So ren *.txt *.bak renames every .txt file in the folder to the same base name with a .bak extension in one line. ren report_*.pdf 2025_*.pdf swaps a leading report_ for 2025_ across a whole batch. The wildcard positions in the second argument map to the matched positions in the first, which is what makes bulk extension and prefix changes a one-liner.
Two limits are worth knowing up front, because they shape everything after. First, ren cannot move a file. The target is always a name in the same folder, so you cannot use ren to rename and relocate in one step. Second, ren has no counter of its own. It can copy characters from the old name into the new name, but it cannot generate fresh incrementing text like 001, 002, 003 by itself. The moment you want sequential numbering, you have to step up to a FOR loop and supply the counter yourself.
Looping With FOR in a Batch File
To rename many files with logic, ren goes inside a FOR loop. FOR walks a set of files and runs a command for each one. A basic pass over every PDF in the current folder looks like for %%f in (*.pdf) do ren "%%f" "renamed_%%f", where %%f holds each filename in turn. Use FOR /R instead of plain FOR when you want to recurse into subfolders and rename files in a whole tree, not just one directory.
One syntax trap catches everyone once: inside a saved .bat file the loop variable takes two percent signs (%%f), but if you type the same command directly at the cmd prompt it takes one (%f). Same command, different percent count, purely because a .bat file needs the doubled form to survive parsing. If a loop that worked at the prompt fails in your script, this is usually why.
Sequential numbering is the classic reason to loop, and it needs one more piece. Because cmd expands variables when it reads a line, a counter you increment inside the loop won't update the way you expect unless you turn on delayed expansion. Put SETLOCAL ENABLEDELAYEDEXPANSION at the top of the script, keep a counter like set /a n+=1 inside the loop, and reference it with exclamation marks, !n!, rather than percent signs. A working shape is: SETLOCAL ENABLEDELAYEDEXPANSION, set n=0, then for %%f in (*.pdf) do set /a n+=1 followed by ren "%%f" "invoice_!n!.pdf". That renames the folder to invoice_1.pdf, invoice_2.pdf, and so on. If you want zero-padded numbers like 001, you build the padding by hand with a bit of string slicing, since cmd has no format specifier for it, which is exactly the kind of fiddliness that eventually pushes people toward PowerShell.
Saving and Reusing the Script
The payoff of the whole exercise is reuse. Open Notepad, paste your ren and FOR commands, and save the file with a .bat extension (in the save dialog, set the file type to All Files so it doesn't become rename.bat.txt). From then on, double-clicking that file runs every command in order against whatever folder it points at.
Make the script readable while you're at it. Any line beginning with REM is a comment that cmd ignores, so REM Rename all scans to invoice_N.pdf above your loop tells future-you what the script does. A line reading @echo off at the very top hides the commands themselves and just shows results, which makes the window far less noisy.
For recurring jobs you can hand the script to Windows Task Scheduler and have it run on a schedule or at logon, so a nightly folder tidy happens without you touching it. One rule matters more than any of this: test on a copy first. A batch rename has no undo. If a wildcard is slightly off, cmd will happily rename a hundred files the wrong way in a fraction of a second and there is no Ctrl+Z to bring the old names back. Duplicate the folder, run the .bat against the copy, confirm the names came out right, and only then point it at the real files.
Where cmd Batch Scripts Stop
Two walls end the batch-script road, and it's better to meet them here than mid-project.
The first is regex. cmd.exe has no real regular-expression engine. FOR can do limited substring substitution (a FOR variable supports replacing one fixed piece of text with another, like %%~nf with a chunk swapped out), but anything that needs true pattern matching, capture groups, reformatting a date buried in the middle of a name, conditionally reordering parts, matching variable structures, is either painful or flatly impossible in a .bat. This is the natural moment to move to PowerShell, whose Rename-Item paired with the -replace operator and .NET regex handles those transformations cleanly. If your job is really a regex job, don't fight cmd for it.
The second wall is the one this whole guide has been pointing at: content. A batch script renames by name, and only by name. It cannot open a PDF and read the vendor, the invoice number, or the date off the page, because it never looks inside the file at all. For a scanned document this is absolute. A scan is an image with no text layer, so even a tool that could read text would find nothing without OCR, and cmd reads no text either way. True content-based renaming needs text extraction for born-digital PDFs or OCR for scans, and cmd.exe does neither. That capability lives in a different category of tool entirely, and it's the right place to hand the job off when the name you want is printed on the page rather than sitting in the old filename.
What a Batch Script Can and Can't Do
| Task | Batch (.bat / cmd) approach | Possible? |
|---|
| Simple pattern / extension rename | ren with wildcards, e.g. ren *.txt *.bak | Yes |
| Sequential numbering | FOR loop with a counter variable | Yes, with delayed expansion |
| Find-and-replace across names | Limited string substitution inside a FOR variable | Partly |
| Regex reformat of names | No regex engine in cmd | Not in cmd, use PowerShell |
| Content-based name from a scan | cmd never reads file contents | Not possible, needs OCR |