I wrote the following script to recursively remove any folders that are empty. I have tested this in a sandbox and it appears to be safe. That is, it will only remove a folder if it is empty and it will only navigate within subfolders within the starting parent folder and won't inadvertently go further up in the directory.
So, if you could take a quick look at my script and tell me if you see any dangers, I would appreciate. Thank you!
$isEmpty=1
$iteration=0
while ($isEmpty) {
$isEmpty=0
$iteration++
get-childitem -Directory -Force -recurse | ForEach-Object {
$count=(Get-ChildItem -Path $_.FullName -Force).count
if ($count -eq 0) {
$isEmpty=1
Write-Host "$iteration`t$count`t$_"
$path="\\?\"+$_.FullName
$folder= Get-item -Path $path
$folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::ReadOnly
$folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::Hidden
Remove-Item -Force -LiteralPath $path
}
}
}
$isEmpty=1
,$isEmpty=0
While 1
and 0
do work as implicit Boolean values, it's better to use Booleans explicitly, i.e. $true
and $false
: $isEmpty = $true
, $isEmpty = $false
Get-ChildItem -Path $_.FullName
If you know paths to be literal (verbatim) paths rather than wildcard expressions, use -LiteralPath
instead of -Path
.
Get-Item -Path $path
The -LiteralPath
recommendation applies equally, but, more importantly:
-Force
is needed to target hidden items with Get-Item
or Get-ChildItem
.
$folder.Attributes = $folder.Attributes -band -bnot [System.IO.FileAttributes]::ReadOnly
[...]
You do not need to explicitly clear the Hidden
and ReadOnly
attributes from file-system items in order for Remove-Item
to remove them - using -Force
is sufficient.
Taking a step back:
You can avoid multiple traversals of your folder subtree if you process directories (folders) bottom up, i.e. if you start with the leaf directories in the directory subtree and iteratively traverse upward:
Get-ChildItem -Directory -Force -Recurse |
Sort-Object -Descending { ($_.FullName -split '[\\/]').Count } |
Where-Object {
if (-not ($_ | Get-ChildItem -Force | Select-Object -First 1)) {
$_ | Remove-Object -Force -WhatIf
}
}
Note:
The -WhatIf
common parameter in the command above previews the operation. Remove -WhatIf
and re-execute once you're sure the operation will do what you want.
That said, given the iterative nature of your task, -WhatIf
will only show you the empty leaf directories that would get deleted and not any of their ancestors that would also get deleted as a result of deleting any leaves.
-WhatIf
) will tell you the actual results.