Reputation: 8621
I'm attempting to do some specific operations with the names of folders and files in a set directory.
This is my powershell script:
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("_","") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace(" ","") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("hp","HP ") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("HP","HP ") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("Hp","HP ") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("&"," & ") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("a","A") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("b","B") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("c","C") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("d","D") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("e","E") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("f","F") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("g","G") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("h","H") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("i","I") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("j","J") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("k","K") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("l","L") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("m","M") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("n","N") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("o","O") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("p","P") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("q","Q") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("r","R") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("s","S") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("t","T") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("u","U") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("v","V") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("w","W") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("x","X") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("y","Y") }
Get-ChildItem -recurse -name | ForEach-Object { Move-Item $_ $_.replace("z","Z") }
I know, it's essentially a bunch of loops.
I had a couple of problems and questions:
HP 14-Z040wm
, file inside is HP14-Z040WM
(I tagged batch-file as well, as I would definitely accept (my first choice when I started making this) a batch file solution.
Upvotes: 0
Views: 878
Reputation: 32170
First, only get items once, then process them once. Next, you can replace the character substitution with the ToUpper()
method. Third, since all those methods return strings, you can just chain the methods together.
It's easy enough for files:
Get-ChildItem -Recurse -File | ForEach-Object {
$NewName = $_.Name.ToUpper().Replace('_','').Replace(' ','').Replace('HP', 'HP ');
Rename-Item -Path $_.FullName -NewName $NewName;
}
Folders, however, are a whole other ball of wax. You can't rename a folder path to the same name, and path names are case-insensitive. So neither Rename-Item
nor Move-Item
will work alone. You'll have to use a temporary folder name.
Here's code for both files and folders:
#Unique name for temp folder
$TempFolderName = [System.Guid]::NewGuid().Guid;
Get-ChildItem -Recurse | ForEach-Object {
$NewName = $_.Name.ToUpper().Replace('_','').Replace(' ','').Replace('HP', 'HP ');
if (!$_.PSIsContainer) {
#Regular file
Rename-Item -Path $_.FullName -NewName $NewName;
}
else {
#Get the parent folder
$ParentFolder = Split-Path $_.FullName;
#Rename folder to temp name
Rename-Item -Path $_.FullName -NewName (Join-Path $ParentFolder $TempFolderName);
#Rename temp name to folder
Rename-Item -Path (Join-Path $ParentFolder $TempFolderName) -NewName (Join-Path $ParentFolder $NewName);
}
}
Upvotes: 3
Reputation: 46700
You should rename files first then folders. Trying to do both at the same time could invalidate other objects in the pipeline and get you errors. Also the repetition here can be saved with -replace "\s|_" and
.ToUpper().
-replace` is a regex function that we are using to replace all space and underscores with nothing. You can chain these as well so we are also going to replace HP at the start of the name and add in the space.
$path = "C:\Temp"
Get-ChildItem $path -Recurse -Directory | Rename-Item -NewName {($_.Name).ToUpper() -replace "\s|_"} -WhatIf
Get-ChildItem $path -Recurse -File | Rename-Item -NewName {($_.Name).ToUpper() -replace "\s|_"} -WhatIf
I have put -WhatIf
on there for testing. If this code is only going to change the case of the entity names then it is going to give an error that the file/folder name needs to be different (folders in are case insensitive). So you would need to move it to a temporary folder first. Windows is not case sensitive so it will see you trying to name the object the same.
You need to be very careful running this code as it permanently changes folder names to temporary names. If the process fails you would have to manually fix the broken folders. Look for .bak folders in that case. My tests did work however so hopefully it is just a precaution. Run your own tests to be sure.
$path = "C:\Temp"
# Rename folders
Get-ChildItem $path -Recurse -Directory | ForEach-Object{
# Save the current name
$originalName = $_.Name
# Make sure the temp name is unique.
$temp = Rename-Item -Path $_.FullName -NewName "$originalName.bak" -PassThru
# Rename using the saved name and proposed changes.
$temp | Rename-Item -NewName ($originalName.ToUpper() -replace "\s|_" -replace "^HP","HP ")
}
Get-ChildItem $path -Recurse -File | Rename-Item -NewName {$_.Name.ToUpper() -replace "\s|_" -replace "^HP","HP "}
Upvotes: 1