Reputation: 1480
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
foldername (lowerCase)
abc
cab
dab
like this (UPPERCASE)
ABC
CAB
DAB
Thanks in advance
Upvotes: 2
Views: 4140
Reputation: 1
How to double quotes folder names ? Some folders has spaces ...
write-host cmd /c ren $.fullname $.name.toupper()
Upvotes: -1
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
.
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, useGet-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
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