/ Development

Batch file rename with PowerShell and Regular Expressions

There have been a few times in the past where I've had to rename a large number of files for various reasons (ie: remove a common piece of text from the name) and I've always defaulted to PowerShell.

Piping dir into a where and matching the files I wanted to rename was effective but tedious. Cue the mass_rename.ps1 script:

$ext = $args[0];
$dir = $args[1];
$what = $args[2];
$with = $args[3];
$whatif = $args[4];
$count = 0;

if ($args.length -lt 4) {
    write - host "Invalid parameters" - fore red;
    write - host " .\mass_rename.ps1 <ext> <dir> <what> <with> [-whatif]";
    write - host " Example (don't do any replacing, -whatif):";
    write - host " .\mass_rename.ps1 .docx c:Documents 'version 1.1' 'version 1.2' -whatif";
    exit 1;

ls - recurse - path $dir | ? {
    ($_.name.endswith($ext)) -and ($_.name -imatch $what)
} | %{
    if ($whatif -eq "-whatif") {
        write-host ("whatif: '" + $_.fullname + "' -> '" + ($_.name -ireplace $what, $with) + "'");
    } else {
        $from = $_.fullname;
        $to = ($_.name -ireplace $what, $with);
        mv -literalpath $from -destination($_.directoryname + "" + $to) -force;
        write -host "Renamed '$from' -> '$to'" -fore yellow;

write - host "Done. Processed $count files." - fore green

The script will accept 4 parameters with an optional -whatif as the 5th. Fairly self explanatory with one mention: the $what parameter is a regular expression. Keep this in mind when, for example, you are trying to match for a period (.) as you would have to escape it (as per the example usage).

The -whatif parameter will only output the before and after file names without doing any actual renaming.

That's it, set the execution policy and enjoy.