Method 1: Rename-Item for One File or a Simple Batch
Rename-Item is the core cmdlet. For a single file it's a one-liner: Rename-Item -Path 'report.txt' -NewName 'report-final.txt'. The power comes when you feed it many files through the pipeline and compute each new name with a script block, the {} after -NewName, where $_ is the current file.
For example, to add a prefix to every .txt file in a folder: Get-ChildItem -Filter *.txt | Rename-Item -NewName { '2025_' + $_.Name }. Get-ChildItem lists the files, the pipe hands each one to Rename-Item, and the script block builds the new name from the old one. Use $_.BaseName for the name without its extension and $_.Extension for the extension, so you can rebuild a name precisely, for instance { $_.BaseName + '_draft' + $_.Extension }.
Two switches on Get-ChildItem make the selection sharper. Add -File so folders are never caught up in a batch meant for files, and add -Recurse to walk every subfolder, for example Get-ChildItem -Filter *.txt -File -Recurse. When you only want part of a folder, insert a Where-Object filter before the pipe to Rename-Item, so you can match on name, size, or date. Get-ChildItem | Where-Object { $_.LastWriteTime -gt (Get-Date).AddDays(-7) } | Rename-Item -NewName { 'recent_' + $_.Name } touches only files changed in the last week.
Method 2: -replace for Pattern and Regex Renames
The -replace operator is what turns PowerShell into a real bulk renamer. It takes a regular expression and a replacement, so you can do far more than a literal swap. To replace spaces with underscores across a folder: Get-ChildItem | Rename-Item -NewName { $_.Name -replace ' ','_' }. To strip a common prefix: { $_.Name -replace '^IMG_','' }. To change every .jpeg extension to .jpg: Get-ChildItem -Filter *.jpeg | Rename-Item -NewName { $_.Name -replace '\.jpeg$','.jpg' }.
Because -replace is regex, you can capture and reorder parts of a name. { $_.Name -replace '(\d{4})-(\d{2})-(\d{2})','$3-$2-$1' } flips a date from YYYY-MM-DD to DD-MM-YYYY across every matching file. That's the kind of transformation the graphical tools and the old ren command simply can't do.
Method 3: Sequential Numbering With a Counter
When you want files numbered in order, keep a counter variable and increment it in the loop. A ForEach-Object gives you room to do that:
- Set a starting number: $i = 1
- Pipe the files and rename each with the padded counter: Get-ChildItem -Filter *.jpg | ForEach-Object { Rename-Item $_ -NewName ('Vacation_{0:D3}.jpg' -f $i); $i++ }
- The {0:D3} format pads the number to three digits (001, 002, ...), so the files sort correctly.
- Run it with -WhatIf first (add -WhatIf to the Rename-Item) to confirm the numbering before it's applied.
Rename Safely: -WhatIf and -PassThru
A rename script applies to every matching file at once, so a mistake scales instantly. Two switches make it safe. -WhatIf performs a dry run: PowerShell prints exactly what each file would be renamed to without touching anything, so you can read the plan before committing. Add it to any Rename-Item and remove it once the output looks right.
-PassThru makes Rename-Item return the renamed objects, which is handy for confirming a large batch or piping the results onward. And if a rename could collide, two files resolving to the same new name, test with -WhatIf first, because PowerShell will error on the collision rather than overwrite silently. The usual fix for a collision is to add a distinguishing part to the new name, such as a sequential counter or a piece of the original name, so every result is unique. It is also worth running the command from inside the target folder, or passing an explicit -Path, so a stray match in another directory never gets swept into the batch. When the path itself changes, not just the name, reach for Move-Item instead of Rename-Item.