Janus
Janus

Reputation: 5681

Rename a list of files

I need to rename all files below pwd named all_v4_0.csv to all_v4_1.csv. So far, I have worked my way to this piece of PowerShell:

$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}
foreach ($o in $oldfiles) {
    $o.CopyTo Join-Path $o.Directory.ToString() "all_v4_1.csv"
}

But the foreach loop fails with the message that

At line:2 char:15
+     $o.CopyTo Join-Path $o.Directory.ToString() "all_v4_1.csv"
+               ~~~~~~~~~
Unexpected token 'Join-Path' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken

What am I doing wrong here?


Update, 20150604

As commented below by Manuel Batsching, the original version can be fixed by adding two layers of parentheses: one to indicate function argument, and one to force evaluation order:

$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}
foreach ($o in $oldfiles) {
    $o.CopyTo((Join-Path $o.Directory.ToString() "all_v4_1.csv"))
}

For the problem at hand, one of the solutions with .FullName.Replace would probably be easier.

Upvotes: 0

Views: 89

Answers (4)

Richard
Richard

Reputation: 109180

PSH's parser is not reading the Join-Path and its arguments as an expression to evaluate and pass result to outer expression. So parentheses to force evaluation order.

But additionally CopyTo is a .NET member, rather than a PSH cmdlet, so it needs to have parentheses around its argument (and no space).

Thus:

$o.CopyTo((Join-Path $o.Directory.ToString() "all_v4_1.csv"))

(Possibly using PSH's Copy-Item cmdlet would be a cleaner option.)

Upvotes: 1

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200533

Simply replace the substring in the new name of the files:

Get-ChildItem -Recurse -Include 'all_v4_0.csv' |
  Rename-Item -NewName { $_.Name.Replace('4_0', '4_1') }

Upvotes: 1

Manuel Batsching
Manuel Batsching

Reputation: 3616

If you want to keep things simple you can also use string concatenation to create the target path.

Get-ChildItem -Recurse -Include 'all_v4_0.csv' | 
    ForEach { $_.MoveTo($_.Directory.FullName + '\all_v4_1.csv') }

Upvotes: 1

arco444
arco444

Reputation: 22881

Set the target name separately before doing the copy. The below should work:

$oldfiles = dir -recurse | ?{$_.Name -eq "all_v4_0.csv"}

foreach ($o in $oldfiles) {
    $newName = $o.FullName.replace("all_v4_0.csv","all_v4_1.csv")
    Copy-Item $o.FullName $newName
}

Upvotes: 1

Related Questions