2024-07-16 12:59:22 -06:00

134 lines
4.0 KiB
PowerShell

<#
.SYNOPSIS
Svendsen Tech's generic script for removing empty directories from a
directory tree structure.
Finds or removes/deletes empty directories recursively from the drive or
directory you specify.
You will need to use the -VerifyNoEmpty parameter or multiple
runs to get rid of nested empty directories. See the -VerifyNoEmpty parameter's
description for further details.
This isn't the most efficient approach as the ones I can think of seem to
increase the script's complexity considerably. It should be useful for a
multitude of use cases.
Author: Joakim Svendsen
.PARAMETER Path
Required. Base root path to iterate recursively.
.PARAMETER Find
Default behaviour where it just prints. Overrides -Remove if both are specified.
.PARAMETER Remove
Removes all empty dirs (as in actually deletes them with Remove-Item).
.PARAMETER VerifyNoEmpty
Makes the script run until no empty directories are found. This is in order
to handle nested empty directories, as in a directory that currently only
contains an empty directory would be empty after the first run/iteration and
need to be remove in a subsequent run. Specifying this parameter causes the
script to run until it's done a complete run without finding a single empty
directory. This might be time-consuming depending on the size of the directory
tree structure.
If there is an error while deleting a directory, it will not run again, to
avoid an infinite loop.
#>
param(
[Parameter(Mandatory=$true)][string] $Path,
[switch] $Find,
[switch] $Remove,
[switch] $VerifyNoEmpty
)
Set-StrictMode -Version 2.0
$ErrorLog = 'remove-empty-dirs-error.log'
######## START OF FUNCTIONS ########
function Iterate-And-Remove-Empty-Dirs {
$FoundEmpty = $false
#Write-Host "Iterating '$Path'"
Get-ChildItem -Force -Recurse -Path $Path | Where-Object { $_.PSIsContainer } | ForEach-Object {
if ($Find -or -not $Remove) {
if (-not (Get-ChildItem -Force $_.FullName)) {
# Directory should be empty
$_.FullName + ' is empty'
}
}
# This is the dangerous part
elseif ($Remove) {
if (-not (Get-ChildItem -Force $_.FullName)) {
$FoundEmpty = $true
# Directory should be empty
Remove-Item -Force $_.FullName
if (-not $?) {
Write-Host -ForegroundColor Red "Error: $(Get-Date): Unable to delete $($_.FullName): $($Error[0].ToString))"
"Error: $(Get-Date): Unable to delete $($_.FullName): $($Error[0].ToString))" | Out-File -Append $ErrorLog
$FoundEmpty = $false # avoid infinite loop
}
else {
Write-Host -ForegroundColor Green "$(Get-Date): Successfully deleted the empty folder: $($_.FullName)"
}
}
}
} # end of ForEach-Object
$FoundEmpty
} # end of function Iterate-And-Remove-Empty-Dirs
######## END OF FUNCTIONS ########
if (-not (Test-Path -Path $Path -PathType Container)) {
"The specified path does not exist. Exiting with code 1."
exit 1
}
if ($Remove -and $VerifyNoEmpty) {
$Counter = 0
while (($OutsideFoundEmpty = Iterate-And-Remove-Empty-Dirs) -eq $true) {
$Counter++
#Write-Host -ForegroundColor Yellow "-VerifyNoEmpty specified. Found empty dirs on run no ${Counter}. Starting next run."
}
$Counter++
#Write-Host "Made $Counter runs in total"
}
else {
Iterate-And-Remove-Empty-Dirs
}