1

I'm trying to rename the following files in a batch:

image.part-Frag1 image.part-Frag10 image.part-Frag11 
> Get-ChildItem *frag* | Rename-Item -NewName "$($_.Name).png" 

... but am getting the following error:

Rename-Item : Cannot create a file when that file already exists. At line:1 char:24 + Get-ChildItem *frag* | Rename-Item -NewName "$($_.Name).png" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (C:\Users\user\Des...html.part-Frag1:String) [Rename-Item], IOException + FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand Rename-Item : Cannot create a file when that file already exists. At line:1 char:24 + Get-ChildItem *frag* | Rename-Item -NewName "$($_.Name).png" + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : WriteError: (C:\Users\user\Des...tml.part-Frag10:String) [Rename-Item], IOException + FullyQualifiedErrorId : RenameItemIOError,Microsoft.PowerShell.Commands.RenameItemCommand Rename-Item : Cannot create a file when that file already exists. At line:1 char:24 + Get-ChildItem *frag* | Rename-Item -NewName "$($_.Name).png" ... 
1
  • In short: The automatic $_ variable (whose alias is $PSItem) is only ever meaningfully defined inside script blocks ({ ... }), such as in ForEach-Object and Where-Object calls, calculated properties, and delay-bind script blocks, which are required in your case. See this answer for details. Commented Jan 29 at 19:04

3 Answers 3

3

Although it seems these are not complete files (fragments of a larger download perhaps), the main issue with your code is that you need to use a scriptblock on the -NewName parameter in order to use the $_ automatic variable as sirtao already showed in his answer.

But also, beware that piping files directly from Get-ChildItem into the Rename-Item cmdlet may result in trying to rename files that already have been renamed.

To prevent that from happening, enclose the Get-ChildItem part of the code in brackets so it will enumerate the files to fetch completely before sending them through the pipe to rename them.

(Get-ChildItem -Filter '*.part-frag*' -File) | Rename-Item -NewName { '{0}.png' -f $_.Name } 

or first capture the enumerated files in a variable and use that to rename the files

$fragFiles = Get-ChildItem -Filter '*.part-frag*' -File $fragFiles | Rename-Item -NewName { '{0}.png' -f $_.Name } 
Sign up to request clarification or add additional context in comments.

3 Comments

in what cases there is double renaming? I don't think it ever happened to me.
@sirtao in cases like this, when the filter also applies on renamed files, you might see that Get-ChildItem picks up those renamed files again. The more files you need to process, the higher the chance of this happening.
@sirtao, see also.
2

It does exist: using "$($_.Name).png" you end up creating a file named .png because $_ is not accessible the way you wrote it and thus defaults to null which gets converted to a empty string and then hained to .png.

Solution: encapsulate it in a scriptblock: Get-ChildItem *frag* | Rename-Item -NewName { "$($_.Name).png" }

2 Comments

Thanks! This did it. Why is $_ not accessible the way I wrote it, and why does a scriptblock make it accessible?
the short version is that $_ can only be used in scriptblocks. The longer version is Here
0

-whatif is your friend:

echo hi > frag Get-ChildItem *frag* | Rename-Item -NewName "$($_.Name).png" -whatif What if: Performing the operation "Rename File" on target "Item: C:\Users\js\foo\frag Destination: C:\Users\js\foo\.png". 

With scriptblock and slight changes. Usually if you can pipe to a parameter like -NewName, you can use a scriptblock with it.

(Get-ChildItem *frag*) | Rename-Item -NewName { $_.Name + '.png' } -whatif What if: Performing the operation "Rename File" on target "Item: C:\Users\js\foo\frag Destination: C:\Users\js\foo\frag.png". 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.