One of my hobbies is photography.  Naming image files so that they are useful can take a significant amount of time.  Personally I like to name them by subject and by date so that they sequence nicely in Windows Explorer.  I'm sure there are hundreds of application that already have this feature, but being a geek and wanting to lean something new I decided to figure out how to perform the task in PowerShell.

The first thing I needed to figure out was how to select a group of files.  I found that the cmdlet Get-ChildItem works nicely for this.


get-childitem -path "c:\pics\RenFair2007"


This is fine for selecting everything in a directory, but what if I only want a range of files in the direcotry?  This is the point at which the Where-Object cmdlet comes in handy.


get-childitem -path "c:\pics\RenFair2007" | where-object -filterscript {($_.Name -ge 'DSC_20') -and ($_.Name -le 'DSC_31')}


The next step is to loop through the results and rename the files.  This takes two cmdlets, ForEach-Object and Rename-Item.  Here is the final statement.


get-childitem -path "c:\pics\RenFair2007" | where-object -filterscript {($_.Name -ge 'DSC_20') -and ($_.Name -le 'DSC_31')} | foreach-object -process {rename-item -path $_.FullName -newname ($prefix + $idx++ + '.jpg')}


Of course this can be shortened up some by using aliases.


get-childitem -path "c:\pics\RenFair2007" | where -filterscript {($_.Name -ge 'DSC_20') -and ($_.Name -le 'DSC_31')} | foreach -process {ren -path $_.FullName -newname ($prefix + $idx++ + '.jpg')}


You will notice that there are two variables, $prefix and $idx.  These will be input parameters on the command line when this is turned into the script.  This final product is the listing below.


if($Args.Length -lt 5)
{
write-output 'usage: rename_pics.ps1 <path> <firstFileName> <lastFileName> <prefix> <startIndex>

<path>          = path to directory holding files to be renamed
<firstFileName> = characters at beginning of the first file to be renamed
<lastFileName>  = characters at beginning of the last file to be renamed
<prefix>        = characters to be used as the begnning of the new file names
<startIndex>    = fist number in the sequence portion of the file name

NOTES:
1 - Files to be renamed must be in a sequential group alphabetically. 
2 - The prefex will have an underscore "_" and a sequential index number appended to it'
}
else
{
$idx = $Args[4]
$picpath = $Args[0]
$minname = $Args[1]
$maxname = $Args[2]
$prefix = $Args[3]

get-childitem -path $picpath | where -filterscript {($_.Name -ge $minname) -and ($_.Name -le $maxname)} | foreach -process {ren -path $_.FullName -newname ($prefix + '_' + $idx++ + '.jpg')}
}