Skip to content

Instantly share code, notes, and snippets.

@sba923
Last active January 31, 2024 14:49
Show Gist options
  • Save sba923/571e7b02bddab9c587ee97110b898629 to your computer and use it in GitHub Desktop.
Save sba923/571e7b02bddab9c587ee97110b898629 to your computer and use it in GitHub Desktop.
# this is one of Stéphane BARIZIEN's public domain scripts
# the most recent version can be found at:
# https://gist.github.com/sba923/571e7b02bddab9c587ee97110b898629#file-remove-emptydirectories-ps1
param([string] $Path, [switch] $IgnoreSystemFiles, [switch] $torecyclebin, [switch] $ContinueOnErrors)
Set-StrictMode -Version 2.0
$VerbosePreference = 'Continue'
$systemfiles = @('thumbs.db', 'desktop.ini', 'PPMetaData.bin', '.ppinfocache', 'ZbThumbnail.info', 'PCM.db')
# derived from http://stackoverflow.com/questions/502002/how-do-i-move-a-file-to-the-recycle-bin-using-powershell
Add-Type -AssemblyName Microsoft.VisualBasic
function Remove-Item-ToRecycleBin($Path)
{
$item = Get-Item -Path $Path -ErrorAction SilentlyContinue
if ($null -eq $item)
{
Write-Error("'{0}' not found" -f $Path)
}
else
{
$fullpath = $item.FullName
Write-Verbose ("Moving '{0}' to the Recycle Bin" -f $fullpath)
if (Test-Path -LiteralPath $fullpath -PathType Container)
{
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory($fullpath, 'OnlyErrorDialogs', 'SendToRecycleBin')
}
else
{
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($fullpath, 'OnlyErrorDialogs', 'SendToRecycleBin')
}
}
}
function IsEmptyOrContainsOnlySystemFiles([string] $Path, [switch] $IgnoreSystemFiles)
{
$contents = (Get-ChildItem -Force -LiteralPath $Path | Where-Object { (!$IgnoreSystemFiles) -or ($_.Name -notin $systemfiles) })
if ($null -eq $contents)
{
return $true
}
else
{
if ($contents.GetType().Name -match '(File|Directory)Info')
{
return $false
}
else
{
return($contents.Count -eq 0)
}
}
}
function Remove-EmptyDirectories([string] $Path, [switch] $IgnoreSystemFiles, [switch] $torecyclebin)
{
Write-Debug ("Processing subdirectories within '{0}'" -f $Path)
try
{
Get-ChildItem -Force -Directory -LiteralPath $Path | Foreach-Object {
Remove-EmptyDirectories -path $_.FullName -ignoresystemfiles:$IgnoreSystemFiles -torecyclebin:$torecyclebin
}
if (IsEmptyOrContainsOnlySystemFiles -path $Path -ignoresystemfiles:$IgnoreSystemFiles)
{
$contents = Get-ChildItem -Force -Recurse -LiteralPath $Path
if ($null -eq $contents)
{
Write-Debug ("Removing empty directory '{0}'" -f $Path)
}
else
{
Write-Debug ("Removing '{0}' with the following contents:" -f $Path)
$contents | ForEach-Object {
Write-Debug("{0}" -f $_.FullName)
}
}
if ($torecyclebin)
{
Remove-Item-ToRecycleBin -Path $Path
}
else
{
Remove-Item -Force -Recurse -Verbose -LiteralPath $Path -ErrorAction SilentlyContinue
# retry without -Force if failed with -Force
if (Test-Path -LiteralPath $Path)
{
Remove-Item -Recurse -Verbose -LiteralPath $Path
if (!$? -and !$ContinueOnErrors)
{
Exit(1)
}
}
}
}
else
{
Write-Debug("'{0}' is NOT empty" -f $Path)
}
}
catch
{
Write-Error ("EXCEPTION: " + $_)
}
}
if (-not $PSBoundParameters.ContainsKey('Path')) # testing (typically: running via F5 under ISE)
{
$DebugPreference = 'Continue'
# create test data
$testroot = $env:TEMP + '\a'
Remove-Item -Force -Recurse -LiteralPath $testroot -ErrorAction SilentlyContinue
mkdir $testroot | Out-Null
mkdir "$testroot/b" | Out-Null
mkdir "$testroot/c" | Out-Null
mkdir "$testroot/c/d" | Out-Null
"foo" | out-file "$testroot/c/d/file_in_d"
mkdir "$testroot/b/e" | Out-Null
mkdir "$testroot/b/e/f" | Out-Null
mkdir "$testroot/b/e/f/g" | Out-Null
"foo" | Out-File -FilePath "$testroot/b/e/f/g/thumbs.db"
"foo" | Out-File -FilePath "$testroot/b/e/thumbs.db"
"foo" | Out-File -FilePath "$testroot/b/e/file_in_e"
Remove-EmptyDirectories -path $testroot -ignoresystemfiles:$true -torecyclebin:$true
if (Test-Path -LiteralPath $testroot)
{
Invoke-Item -LiteralPath $testroot
}
else
{
Write-Host -Object ("'{0}' has been completely removed" -f $testroot)
}
}
else
{
Remove-EmptyDirectories -path $Path -ignoresystemfiles:$IgnoreSystemFiles -torecyclebin:$torecyclebin
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment