/\/\o\/\/ PowerShelled

This blog has moved to http://ThePowerShellGuy.com Greetings /\/\o\/\/
$AtomFeed = ("Atom.xml")
$PreviousItems = (" PowerShell : Playing with LeapYears "," Download PowerShell 1.0 RTM "," PowerShell goes RTM "," Windows PowerShell Week on ScriptCenter "," PowerShell : How Can I Split a String Only on Spec... "," PowerShell : How Can I Tell Whether a Number is Ev... "," PowerShell : 99-bottles-of-beer "," PowerShell : Tabcompletion Part 5 "," PowerShell : Calendar Function (GUI) "," PowerShell : WMI Support in RC2 : Privileges and c... "," ")

Saturday, November 25, 2006

 


PowerShell : Advanced renaming of files



On the NewsGroup microsoft.public.windows.powershell ,

there was a Question about : Advanced renaming directly in Powershell? 

The Question was about doing advanced file renaming, to rename a set of files like this :

file.ex2
file.ext
file_1.ex2
file_1.ext
file_2.ext

to the following format, Giving a base number and then rename the files and use the _3 as an offset to the number

file12.ex2
file12.ext
file13.ex2
file13.ext
file14.ext

Now the rename-object commandlet in PowerShell is very powerfull for this, some basic renaming might be a bit hard at first see also /\/\o\/\/ PowerShelled: PowerShell : How Can I Rename Files Using ... (a CSV file) and commments on this post Upgrading MSH, My first Windows PowerShell Commands about renaming *.msh to *.ps1,

But as the -NewName parameter takes a ScriptBlock as a parameter it is very handy to use some more advanced logic to rename file as you also can use the Power of the -Match and -Replce Operators RegEx support.

I Came up with this oneliner for this task :

PoSH>$num = 12
PoSH>ls file*.ex* | rename-item -newname {if($_.name -match '_(\d)'){$num = $num + $matches[1]};$_.name -replace "file.*\.", "file$num."} -WhatIf

What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ex2 Destination: C:\PowerShell\file12.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ext Destination: C:\PowerShell\file12.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ex2 Destination: C:\PowerShell\file13.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ext Destination: C:\PowerShell\file13.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_2.ext Destination: C:\PowerShell\file14.ext".

As there is happening a lot in this one line of code I'm going to work it out a bit more in this post.

lets first make the files and list them :

PoSH>sc file.ext 'a'
PoSH>sc file.ex2 'a'
PoSH>sc file_1.ex2 'a'
PoSH>sc file_1.ext 'a'
PoSH>sc file_2.ext 'a'

PoSH>ls file*.ex*

Directory: Microsoft.PowerShell.Core\FileSystem::C:\PowerShell

Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 11/25/2006 1:55 PM 3 file.ex2
-a--- 11/25/2006 1:54 PM 3 file.ext
-a--- 11/25/2006 1:55 PM 3 file_1.ex2
-a--- 11/25/2006 1:55 PM 3 file_1.ext
-a--- 11/25/2006 2:15 PM 3 file_2.ext

Now that we have listed the files we want to act upon ( al files starting with file and ending with .ex* )

we can pipe them to rename object :

PoSH>ls file*.ex* | rename-item -newname {$_.name} -WhatIf

What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ex2 Destination: C:\PowerShell\file.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ext Destination: C:\PowerShell\file.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ex2 Destination: C:\PowerShell\file_1.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ext Destination: C:\PowerShell\file_1.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_2.ext Destination: C:\PowerShell\file_2.ext".

Note that in the scriptblock I provided to the -newname parameter I have access to the complete File Object in the $_ variable, I just use it to get the name property and do not do any processing yet, also note that I added the -WhatIf parameter so no changes are made and I we can test freely till we got it right without messing up your testfiles.

Now lets start by adding the Base Number for it, in this case 12 that I put in the variable $num

PoSH>$num = 12


PoSH>ls file*.ex* | rename-item -newname {$_.name -replace "file.*\.", "file$num." } -WhatIf

What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ex2 Destination: C:\PowerShell\file12.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ext Destination: C:\PowerShell\file12.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ex2 Destination: C:\PowerShell\file12.ex2".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ext Destination: C:\PowerShell\file12.ext".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_2.ext Destination: C:\PowerShell\file12.ext".

In this first step we use the -replace operator to insert the basenumber given into the filename by replacing everything between the word file and the extension.

note that -replace uses RegEx expressions not wildcards so the expression looks like this : "file.*\." first the word file, then we need to use a dot . before the * that means any character and we need to escape the last (literal) dot by escaping it \.

but as you can see in the following steps this makes it much more powerfull as also the -mach operator uses the regular expression engine, so we can use the full RegEx power.

Next we need to raise the number for filesnames that do contain an _ with the number that is behind it.

we can use the mach operator to do this (note again that we use -WhatIf so are free just to return anything we want) :

PoSH>ls file*.ex* | rename-item -newname {$_.name -match '_' } -WhatIf

What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ex2 Destination: C:\PowerShell\False".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file.ext Destination: C:\PowerShell\False".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ex2 Destination: C:\PowerShell\True".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_1.ext Destination: C:\PowerShell\True".
What if: Performing operation "Rename File" on Target "Item: C:\PowerShell\file_2.ext Destination: C:\PowerShell\True".

The -Mach operator returns $True or $False , but does more it also fills the $maches variable, lets look at this with a single filename to look how this works :

 

PoSH>"file_1.ex2" -match '_'
True

PoSH>$matches

Name Value
---- -----
0 _

PoSH>"file_1.ex2" -match '_\d'
True

PoSH>$matches[0]
_1

You can see here that the $matches variable does contain the Capture found, in the second example I did add \d that means any digit.

but as with a fullBlown [regex] object also the -match operator supports subCaptures, so we can get the Number :

PoSH>$matches

Name Value
---- -----
1 1
0 _1

PoSH>$matches[1]
1

So now we can combine the $true returned by -match and the capture made in $matches with an If statement to do the Math :

PoSH>if ("file_1.ex2" -match '_(\d)'){$matches[1]}
1
PoSH>if ("file_2.ex2" -match '_(\d)'){$matches[1]}
2
PoSH>if ("file_2.ex2" -match '_(\d)'){$num + $matches[1]}
14

and all can be combined the the one-liner I did post on the NewGroup, what also could be written like this in PowerShell to make it a bit more readable and you can still just past it into the PowerShell console

$num = 12 

Dir file*.ex* | 

  rename-item -newname {

    if($_.name -match '_(\d)'){
      $num = $num + $matches[1]
    }

    $_.name -replace "file.*\.""file$num."

  } -WhatIf

 

I hope this post makes it clear how easy it is to make and test advanced rename jobs interactivly on the console by using -WhatIf and command history, and then while ready format as a script, and how powerfull the RegEx support of -match and -Replace is.

Enjoy,

Greetings,
/\/\o\/\/
Tags : PowerShell




Comments: Post a Comment



<< Home

Archives

October 2005   November 2005   December 2005   January 2006   February 2006   March 2006   April 2006   May 2006   June 2006   July 2006   August 2006   September 2006   October 2006   November 2006   December 2006  

$Links = ("PowerShell RC1 Docs"," PowerShell RC1 X86"," PowerShell RC1 X64"," Monad GettingStarted guide"," Monad Progamming Guide"," Monad SDK"," Monad videos on Channel 9"," MSH Community Workspace"," scripts.readify.net "," MonadSource"," www.reskit.net"," PowerShell Blog"," Under The Stairs"," computerperformance powershell Home"," proudlyserving"," MSH on wikipedia"," MSHWiki Channel 9"," Keith Hill's Blog"," Precision Computing"," PowerShell for fun"," MSH Memo (Japanese)"," monadblog")

find-blog -about "PowerShell","Monad" | out-Technorati.
find-blog -contains "","" | out-Technorati.
Google
 
Web mow001.blogspot.com

This page is powered by Blogger. Isn't yours?