Mr.M
Mr.M

Reputation: 1480

rename multiple folder to Uppercase not files using powershell

I am working on powershell where I have multiple folders i need to change all folders names into Uppercase not the files only folder.

I have tried the below code

Get-ChildItem -Path "C:\Users\Xyz\Desktop\sample" -Recurse | % { 
  if ($_.Name -cne $_.Name.ToUpper()) { ren $_.FullName $_.Name.ToUpper() } 
}

But with this code it was changing only file name but I want to change only dir

for example

enter image description here

foldername (lowerCase)

abc
cab
dab

like this (UPPERCASE)

ABC
CAB
DAB

Thanks in advance

Upvotes: 2

Views: 4140

Answers (3)

Thiago Zerbinato
Thiago Zerbinato

Reputation: 1

How to double quotes folder names ? Some folders has spaces ...

write-host cmd /c ren $.fullname $.name.toupper()

Upvotes: -1

mklement0
mklement0

Reputation: 437568

  • To limit Get-ChildItem's output to directories only, use the -Directory switch (PSv3+; in PSv2, pipe to Where-Object { $_.PSIsContainer }

  • Apart from that, your solution should work, but doesn't due to a conceptual flaw in .NET's System.IO.DirectoryInfo.MoveTo() method (and also System.IO.Directory.Move() method), which PowerShell's Rename-Item cmdlet builds on, as of .NET Core 3.0 preview6 / .NET 4.8:

    • The method doesn't recognize case variations of directory name as a different name, and fails with Source and destination path must be different.

      • Curiously, files are not affected, as you've experienced.[1]
    • Of course, while NTFS is case-insensitive, it is also case-preserving, so it should be possible to rename foo to FOO, for instance.

Workaround (PSv4+):

Note: js2010's helpful answer offers another, workaround, based on calling cmd.exe for each input folder to use its ren command. While it is conceptually simpler, the caveat is that this approach of creating a child process for every folder processed is inefficient and slow. That said, for occasional renaming operations that probably won't matter.

$path = 'C:\Users\Xyz\Desktop\sample'

Get-ChildItem -LiteralPath $path -Recurse -Directory |
  Where-Object { $_.Name -cne $_.Name.ToUpper() } -PipelineVariable dir |  
    Rename-Item -PassThru -NewName { [IO.Path]::GetRandomFileName() } |
      Rename-Item -NewName { $dir.Name.ToUpper() }

The workaround temporarily renames matching folders to a transient, randomly generated name ([IO.Path]::GetRandomFileName()) and then applies the all-uppercase version of the original name.

The input folder's original state and name are captured via variable $dir, which is "stashed" away for later use via the common -PipelineVariable parameter.


[1] Caveat: When you use Get-ChildItem or Get-Item to report a specific directory or file by its literal name, whatever case variation you specify is reported back, even though the true case variation as stored in the filesystem may differ (File Explorer, by contrast, always shows you the true case). To see the true case, use
Get-ChildItem <parentDir> -Filter <name>
or, as a quick workaround that may show additional items, however, append * to the name/path. In both cases, the name is treated as a wildcard pattern, and the result of the matching process reflects the true case.

Upvotes: 1

js2010
js2010

Reputation: 27423

These tricks may not be obvious. How's this? Hmm, that didn't actually work. You can't rename folders to the same thing in upper case in powershell.

# doesn't work!
get-childitem -recurse -directory -path "C:\Users\Xyz\Desktop\sample" | 
  Rename-Item -NewName { $_.name.toupper() } -whatif

Sometimes calling cmd from powershell just works better. Try this first as a "whatif" to see if it does what you want. And if I really understand the question. All this does is echo strings. This command is just "pretend".

get-childitem -recurse -directory -path "C:\Users\Xyz\Desktop\sample" | 
  foreach { write-host cmd /c ren $_.fullname $_.name.toupper() }

And if that looks good, this actually does the rename. But maybe make a backup in case something goes wrong. Be able to undo the action.

get-childitem -recurse -directory -path "C:\Users\Xyz\Desktop\sample" | 
  foreach { cmd /c ren $_.fullname $_.name.toupper() }

Upvotes: 4

Related Questions