Reputation: 3
My problem may\may not be complicated but I have been scratching my head and searching for a way to do this but so far have not come up with much.
I have a folder structure like so:
C:\
└───ParentFolder
├───ChildFolder1
│ ├───SubFolderA_1
│ ├───SubFolderA_2
│ ├───SubFolderA_3
│ ├───SubFolderA_4
│ ├───SubFolderB_1
│ ├───SubFolderB_2
│ ├───SubFolderB_3
│ └───SubFolderB_4
└───ChildFolder2
├───SubFolderA_1
├───SubFolderA_2
├───SubFolderA_3
├───SubFolderA_4
├───SubFolderB_1
├───SubFolderB_2
├───SubFolderB_3
└───SubFolderB_4
What I'm looking for is a PowerShell script that would utilize the serialized nature of the "SubFolders" names to delete older versions, leaving only the most recent SubFolders in place.
Using the example above, this would mean the script would delete SubFolderA_1 to SubFolderA_3 and SubFolderB_1 to SubFolderB_3, leaving only SubFolderA_4 and SubfolderB_4 in the ChildFolders.
Would anyone know a way of doing this? I was thinking about Object Sorting + The Recursive Function + pattern matching, but I don't seem to get anywhere with it. I'm a PS noob by the way.
Your help would be much appreciated.
Upvotes: 0
Views: 185
Reputation:
Provided there is only one underscore,
This is quite similar to Lee_Daileys script but will sort with all numbers padded left with zeros to a unique width.
## $ToNatural from Roman Kuzmin source https://stackoverflow.com/a/5429048/6811411
$ToNatural = { [regex]::Replace($_, '\d+', { $args[0].Value.PadLeft(20,"0") }) }
Get-ChildItem C:\ParentFolder\ChildFolder*\Subfolder* |
Group-Object @{e={$_.fullname.split('_')[0]}} | ForEach-Object {
$_.Group | Sort $ToNatural -Descending | Select -Skip 1 | Remove-Item -WhatIf
}
If the output looks OK, remove the trailing -WhatIf
Upvotes: 0
Reputation: 7479
here's one way to do it. [grin] the heart of it is the Group-Object
cmdlet. one thing often overlooked about it is the ability to use a calculated property much as can be done with the Select-Object
cmdlet.
# fake reading in a list of directories
# in real life, use Get-ChildItem -Directory
$DirList = @(
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_1'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_2'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_3'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderA_4'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_1'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_2'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_3'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder1\SubFolderB_4'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_1'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_2'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_3'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderA_4'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_11'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_22'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_3'
[System.IO.DirectoryInfo]'C:\ParentFolder\ChildFolder2\SubFolderB_44'
)
$GroupedDirList = $DirList |
# changed from sorting by the FullName to sorting by the trailing number
# thanks to LotPings for pointing out the glitch with multi-digit numbers
Sort-Object {[int]$_.FullName.Split('_')[1]} |
Group-Object {$_.FullName.Split('_')[0]}
foreach ($GDL_Item in $GroupedDirList)
{
$GDL_Item.Group |
Select-Object -SkipLast 1 |
ForEach-Object {
# remove the quotes, the Write-Host, and the "$()" when you do this for real
# can't use the "-WhatIf" parameter here since the dirs don't actually exist on my system
Write-Host "Remove-Item -LiteralPath $($_.FullName) -Recurse -WhatIf"
}
'=' * 20
}
output ...
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderA_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder1\SubFolderB_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_1 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_2 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderA_3 -Recurse -WhatIf
====================
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_3 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_11 -Recurse -WhatIf
Remove-Item -LiteralPath C:\ParentFolder\ChildFolder2\SubFolderB_22 -Recurse -WhatIf
====================
Upvotes: 1