The move element does not work in a loop

ls *.gif | Foreach { $newname = $_.Name -replace '\[','' -replace '\]','' write-host $_.Name $newname move-Item -Path $_.Name -Destination $newname; } ls *.gif 

Therefore, trying to help someone rename files using [], I found that the move element does not work in a loop. It seems to work just fine outside of the loop.

Ideas?

+6
loops powershell move
source share
4 answers

Update. Based on the comment below, I want to clarify this: special characters in file names require the use of the -LiteralPath parameter. -Path cannot handle these characters. Outside the loop, -Path works, since you execute special characters using `. This is not possible when passing through a collection.

In a loop, you need to use the -LiteralPath parameter instead of -Path.

 -LiteralPath <string[]> Specifies the path to the current location of the items. Unlike Path, the value of LiteralPath is used exactly as it is typed. **No characters are interpreted as wildcards. If the path includes escape characters, enclose it in single quotation marks.** Single quotation marks tell Windows PowerShell not to interpret any characters as escape sequences. 

SO, this will be:

 GCI -Recurse *.txt | % { Move-Item -LiteralPath $_.FullName -Destination "SomenewName" } 
+7
source share

If you use the PowerShell pipeline binding function, you can make it much simpler and eliminate the need for an explicit Foreach-Object for example:

 ls *.gif | Move-Item -Destination {$_ -replace '\[|\]',''} -WhatIf 

This works because the LiteralPath parameter LiteralPath configured to bind ByPropertyName . However, you may wonder where it gets the property named "LiteralPath" from at the output of Get-ChildItem (alias ls). Well, he does not find this property name, however the LiteralPath parameter has a LiteralPath alias defined, which exists for every object displayed by Get-ChildItem . This is due to the LiteralPath parameter. Another tip of the speed here is that since the Destination parameter is also associated with the pipeline (ByPropertyName), you can use scriptblock to provide the value. And inside this script block, you have access to the pipeline object.

Inside the script block, the -replace operator is used to come up with a new name based on the original name. Although I could use $_.FullName or even $_.Name in this case (assuming you want to essentially rename files in the same directory), I only use $_ . Since -replace is a string operator, it will force $_ to the string before using it. You can see what it will be by doing:

 ls *.gif | Foreach {"$_"} 

What is the full path in this case, but you have to be careful because you do not always get the full path, for example:

 ls | Foreach {"$_"} 

only displays the file name. In your examples (rename to the same directory) this does not matter, but in other cases this happens. It's probably a good practice to just be explicit and use $_.Name or $_.FullName in the script, but when hacking this stuff on the console, I usually use only $_ . Saying: this is a sharp stick, do not poke your eye. :-)

+2
source share

You can find the "official" role information " [ " in the Path lines on this Microsoft article .

Or take a look at Google for: Windows PowerShell Tip of the week: β€œTake things (like file paths) literally.”

The only advice that was not clear to me was that Rename-Item does not support LiteralPath and that we can use Move-Item to rename files or directories.

In JP

0
source share

It worked for me (at least in my situation.

 Move-Item -literalpath $_.FullName -Destination ( ( ( (Join-Path -Path (Get-Location) -ChildPath $_.BaseName) -replace "\[","`[") -replace "\]","`]") ) 

There were hundreds of films and related subtitles stored without folders. I decided to put each of the films and subtitles in their own folders

Full code

 Get-ChildItem -File | % { if(Test-Path -LiteralPath ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName )) { Move-Item -literalpath $_.FullName -Destination ( ( ( (Join-Path -Path (Get-Location) -ChildPath $_.BaseName) -replace "\[","`[") -replace "\]","`]") ) } else { New-Item ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName ) -ItemType Directory Move-Item $_ -Destination ( Join-Path -Path (Get-Location) -ChildPath $_.BaseName ) } } 
0
source share

All Articles