0

for a personal project I want to prefix folder and file names with an index. The goal is to have every childitem name remain the same except for the prefix.

My current Script looks as follows:

$vaultDir = $args[0]
$path = Get-ChildItem -Path $vaultDir -Depth 0
ForEach($childObject in $path){
    $index = '{0:d3}' -f $path.IndexOf($childObject)
    $currentFolderName =  $childObject.ToString() | out-string | select-string -pattern '[^\\]+$'
    $newName=($index.ToString()+'-'+$currentFolderName.Matches.value)
    $childObject.FullName |rename-Item -newname {$_.Name -replace '.*', $newName} -whatif
}

The $newName is set correctly. Now I want to iterate through the childitems and rename them.

But honestly I do not get how the rename-item function works.

The -whatif result seems to work(the test folders are named asdfg and tyui):

What if: Performing the operation "Rename Directory" on target "Item: C:\Users\mon0\Documents\Script\kekw\asdfg Destination: C:\Users\mon0\Documents\Script\kekw\000-asdfg
".
What if: Performing the operation "Rename Directory" on target "Item: C:\Users\mon0\Documents\Script\kekw\tyui Destination: C:\Users\mon0\Documents\Script\kekw\001-tyui
".

but when I remove it I get the following error message:

Line |
  19 |  … ject.FullName |rename-Item -newname {$_.Name -replace '.*', $newName}
     |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The filename, directory name, or volume label syntax is incorrect.

Rename-Item: C:\Users\mon0\Documents\Script\Batch-Rename.ps1:19:28
Line |
  19 |  … ject.FullName |rename-Item -newname {$_.Name -replace '.*', $newName}
     |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
     | The filename, directory name, or volume label syntax is incorrect.

Any ideas ?

Ceus
  • 9
  • 1
  • 1
    i see that mklement0 has pointed out the glitch & the fix, so this is just FYI ... DO NOT treat powershell as a _string manipulation_ system like the old BAT/CMD & 'nix stuff. [*grin*] ///// **_powershell is all objects all the time._** your code converts those rich objects into strings and then diddles them. instead, you need to keep those rich objects as rich objects, not simple string objects. take a look at what you get from your `$path` collection [badly named, that] when you feed it to `Get-Member` sometime to realize just how much useful info you threw away ... [*grin*] – Lee_Dailey May 15 '22 at 05:41

1 Answers1

0

Your immediate problem is the - unnecessary - use of Out-String:

Unfortunately, Out-String invariably appends a trailing newline to the stringified output - see GitHub issue #14444 for a discussion of this problematic behavior - which is what causes your problem: what the Select-String regex, '[^\\]+$', matches includes the CR of that trailing newline on Windows.

Therefore, the immediate fix is to simply remove the Out-String call.

However, your code can be greatly simplified:

$vaultDir = $args[0]
$index = @{ Value = 0 }
Get-ChildItem -Path $vaultDir |
  Rename-Item -NewName { '{0:d3}-{1}' -f ++$index.Value, $_.Name } -WhatIf

Note: The -WhatIf common parameter in the command above previews the operation. Remove -WhatIf once you're sure the operation will do what you want.

For an explanation of the technique used above, see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • 1
    You my friend... are a life saver <3 I added the oiut-string hours ago, since somewhere in the documentation it said I should add it for parsing the string correctly in the pipe. Sadly I forget for what cmdlet this was the case. Anyway your code works like a charm and looks beautiful. Much to learn from! Big thank you :) – Ceus May 14 '22 at 20:53