views:

503

answers:

2

I need to rename a lot of directories and their sub directories.

I have a csv file which contains the old directory names and the required new name.

1,blah,old_name1,new_name2,wibble
2,foo,old_name2,new_name2,bar
3,john,old_name3,new_name3,paul
4,george,old_name4,new_name4,ringo

Note that some of the directory names are

old_name1-morestuffhere

which need to be renamed to

 new_name1-morestuffhere

I know broadly how I'd do this in bash:

mv -r `cat file.csv | awk -F, '{print $3* $4*}'`

..but I'm bound to and totally lost with powershell.

EDIT: Here's what I've got so far. Is this close?:

cat .\file.csv | foreach { $oldname = $_.split(",")[2], $newname = $_.split(",")[3], move-item $oldname*, $newname*}
+1  A: 

this is an alternative, since you should have vbscript already installed

Set objFS = CreateObject("Scripting.FileSystemObject")
strFile= "C:\test\file.csv"
Set objFile = objFS.OpenTextFile(strFile,1)
Do Until objFile.AtEndOfStream 
    strLine = objFile.ReadLine
    s = Split(strLine,",")
    oldname = s(2)
    newname = s(3)
    WScript.Echo oldname, newname
    Set objFile=objFS.GetFile(oldname)
    objFile.Name = newname 
    Set objFile=Nothing 
Loop
ghostdog74
+3  A: 

The "-morestuffhere" is the tricky part. The Path parameters (ie source location) on Move-Item and Rename-Item don't take wildcards. But that can be solved another way. First, can you add a CSV header to your CSV file like this:

Index,F2,OldName,NewName,F5
1,blah,old_name1,new_name2,wibble
...

If so, we can use PowerShell's Import-Csv cmdlet. Now the following seems kind of complicated but it handles the case of multiple OldName-<differentstuffhere> to NewName-<sameasoldnamestuffhere> renames.

$names = Import-Csv names.csv | 
             Foreach {
                 $oldDirs=@(Get-ChildItem . -r -filter "$($_.OldName)*" | 
                            ?{$_.PSIsContainer} | %{$_.FullName})
                 Add-Member -in $_ NoteProperty OldDirs $oldDirs -PassThru
             }

foreach ($name in $names) {
    foreach ($oldDir in $name.oldDirs) {
        $dir     = Split-Path $oldDir -Parent
        $suffix  = (Split-Path $oldDir -Leaf).Substring($name.OldName.Length)
        $newPath = Join-Path $dir ($name.NewName + $suffix)
        Rename-Item $oldDir ($name.NewName + $suffix) -WhatIf -ea 0
    }
}

This is hand intrepreted so there may be errors. Remove the -Whatif when you're satisfied with the results.

Keith Hill
Very interesting - I didn't know about Import-Csv.
Charlie