1

I am new to powershell and I am having a hard time applying this one command to all of the subfolders I have. I have used:

ls | Rename-Item -NewName {$_.name -replace "ALL",""}

And this works for only the one subfolder that I am in. This takes the ALL out of the files names as that is not needed for my purposes. How would I go about applying this command to all of the subfolders so I don't have to go in manually and apply them one at a time. So far, I have tried

dir -recurse ls | Rename-Item -NewName {$_.name -replace "ALL",""}

And this ran but didn't do anything to any of the files. I tried a few variations of this as well, but they did not compile.

Any help would be greatly appreciated

phuclv
  • 37,963
  • 15
  • 156
  • 475
Cole
  • 15
  • 3

2 Answers2

3

dir -recurse ls

dir and ls[1] are both aliases of PowerShell's Get-ChildItem cmdlet, so you need:

  • either dir -recurse
  • or ls -recurse
  • or - the best choice if you want to use an alias[2] - gci -recurse
  • or, finally, using the full cmdlet name, Get-ChildItem -Recurse

To see all aliases that are defined for Get-ChildItem, run Get-Alias -Definition Get-ChildItem.

Additionally, to limit processing to files, add the -File switch:

Get-ChildItem -File -Recurse | Rename-Item -NewName { $_.Name -replace 'ALL' }

I'm using '...' quoting instead of "..." quoting for conceptual clarity, given that the string's content is to be used verbatim (no string interpolation needed). Also, omitting the replacement-string operand of the -replace operator defaults to '' (the empty string), so it can be omitted.

Note: The -replace operator is case-insensitive by default, as PowerShell generally is. If you want to match ALL only in all-uppercase, use the case-sensitive variant of the operator,
-creplace.


As for what you tried:

this ran, but didn't do anything to any of the files

  • ls in your dir -recurse ls command was positionally bound to Get-ChildItem's
    -Path parameter.

  • Because of the highly unfortunate behavior of -Path in combination with -Recurse, described in GitHub issue #5699, no error occurred, despite there (presumably) being no file or subdirectory literally named ls.

    • In effect, Get-ChildItem looked for an file or directory named ls on all levels of the subdirectory hierarchy and, in the absence of any, produced no output, i.e. amounted to a quiet no-op.

    • While in your case this behavior amounted to obscure failure, in the worst-case scenario it can be destructive, as discussed in the linked GitHub issue.


[1] on Windows; on Unix-like platforms, ls refers to the platform-native /bin/ls utility.

[2] This is the best choice, because it doesn't use the name of another shell's or platform's similar, but syntactically different command or utility. The name gci is formed according to PowerShell's own naming conventions, where g is the official alias abbreviation of the Get, one of the approved verbs.

mklement0
  • 382,024
  • 64
  • 607
  • 775
-1

A loop through the piped output would be what you are after.

Get-ChildItem -Recurse | ForEach-Object{Rename-Item -Path $_.FullName -NewName $($_.Name -replace "ALL","")}

This will apply the Rename-Item for each line in the piped output.

Drew
  • 3,814
  • 2
  • 9
  • 28
  • Sorry for the redundancy, but in this case I would not change the FullName or -NewName commands, I would just leave that as it is? Or would I change fullname to the "paths" full name so the computer knows where to go and change things? – Cole Mar 10 '22 at 23:50
  • `Rename-Item` is expecting the path of the file it is working on, which is where the `$_.FullName` comes into play within the loop. If you want to change the location that the renaming command takes place, provide the `Get-ChildItem` a `-Path` parameter. – Drew Mar 10 '22 at 23:56
  • 1
    Piping _directly_ to `Rename-Item` with a [delay-bind script block](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_script_blocks#using-delay-bind-script-blocks-with-parameters) is always preferable to a `ForEach-Object` solution - both in terms of conceptual elegance and particularly in terms of performance. It is what @Cole attempted, but fell short due to accidentally using _both_ `dir` and `ls`. – mklement0 Mar 11 '22 at 02:58