Why 'a Folder' Usually Means 'a Folder Tree'
When people say they want to batch rename a folder, they often have subfolders too: a project folder with per-client subfolders, a photo library organized by year, a document archive by department. The trap is that the simplest tools, File Explorer's F2, a plain shell glob, only act on the current directory. Run them at the top and the files nested inside are untouched, so you think the batch worked when half of it didn't.
So the real question for a folder rename is whether the method is recursive. Everything below is chosen for that: reaching every file in the tree, not just the ones sitting at the top.
It helps to decide the scope before you run anything. Sometimes you want only the files sitting directly in one folder, sometimes you want every descendant no matter how deep the tree goes, and sometimes you want the whole tree except for a couple of subfolders you deliberately leave alone. Naming that intent up front, one folder versus all descendants, tells you which switch to reach for and stops you from either under-renaming the top level or accidentally rewriting a nested archive you meant to preserve.
Method 1: Recursive Rename on Windows
PowerShell handles a folder tree cleanly with the -Recurse switch on Get-ChildItem, which walks every subfolder:
- Preview first: Get-ChildItem -Path 'C:\Docs' -Recurse -Filter *.txt | Rename-Item -NewName { $_.Name -replace ' ','_' } -WhatIf
- Read the -WhatIf output to confirm files deep in the tree are included.
- Remove -WhatIf to apply the rename across the whole folder and its subfolders.
- For a no-script option, PowerToys PowerRename also includes items from selected subfolders and shows a live preview before applying.
Method 2: Recursive Rename on Mac and Linux
On macOS and Linux, find is the recursive workhorse. It walks the tree and runs a rename on each match: find . -type f -name '*.txt' -exec sh -c 'mv "$1" "${1%.txt}.md"' _ {} \; changes every .txt to .md throughout the folder and its subfolders. Where a plain for f in *.txt loop would only see the top directory, find reaches everything. On Linux specifically, the Perl rename utility combined with find covers recursive regex renames as well.
Watch for Name Collisions Across Subfolders
Recursion introduces a risk single-folder renames don't: two files in different subfolders can resolve to the same new name, and if you flatten or move them, one overwrites the other. Always preview (with -WhatIf on Windows, a dry run on the terminal) before applying a recursive rename, and keep files in their subfolders unless you specifically intend to merge them. That single habit prevents the most common way a folder-tree rename goes wrong.
Excluding Subfolders and Keeping the Structure Intact
Recursive does not have to mean everything. Often a folder tree has one or two subfolders you want left untouched, an originals folder, a done archive, a node_modules or export directory that has no business being renamed. On Windows you can filter those out by piping through Where-Object and testing the FullName, for example Get-ChildItem -Recurse | Where-Object { $_.FullName -notmatch '\\originals\\' }. On Mac and Linux, find takes a -prune expression that skips whole branches of the tree before it ever runs the rename. Building the exclusion into the command is safer than deleting files from a preview list by hand, because it applies the same rule every time you run it.
It is also worth being clear that renaming files inside a tree does not move them. Each file stays in the subfolder it lived in, so the folder structure, your per-client, per-year, or per-department layout, survives the operation. That matters when the folders themselves carry meaning: a file named 2024-invoice.pdf inside a Client-A folder is already half-labelled by its location, and a good recursive rename can fold that per-folder context into the filename so each file reads correctly even after it is copied out of the tree.