Search code examples
regexpowershell-2.0file-renamebatch-rename

How to use regular expression matching groups in batch renames?


I'm trying to do some regular expression based bulk renames with PowerShell.

This succesfully gives me only the files I need:

Get-ChildItem . | Where-Object { $_.Name -cmatch "(\b|_)(L|H|M|X{1,3})(_|\b)" }

(all those that contain an uppercase L, M, X, ...)

Next, I want to rename, i.e. mycustom_M.png to processed_M.png, another_L.png to processed_L.png, and so forth.

Basically, I would use the regexp .*?(?:\b|_)(L|H|M|X{1,3})(?:_|\b).* to select the names, and processed_\1.png to replace them if I was in Notepad++, but I can't get it to work in PowerShell (I'm surely missing the right syntax here):

[...] | Rename-Item -NewName { $_.Name -replace ".*?(?:\b|_)(L|H|M|X{1,3})(?:_|\b).*","banner_$Matches.groups[1].value" }

Solution

  • Backreferences in PowerShell start with a $, not a \. However, you must either put the replacement expression in single quotes or escape the $, otherwise PowerShell would expand the $1 as a regular variable:

    $pattern = ".*?(?:\b|_)(L|H|M|X{1,3})(?:_|\b).*"
    ... | Rename-Item -NewName { $_.Name -replace $pattern, 'banner_$1' }
    

    or

    $pattern = ".*?(?:\b|_)(L|H|M|X{1,3})(?:_|\b).*"
    ... | Rename-Item -NewName { $_.Name -replace $pattern, "banner_`$1" }