# PowerShell script to recursively delete empty folders

This is a short and simple PowerShell script to recursively delete empty folders from a folder structure. This can be necessary for a multitude of reasons - one of which you might be aware of since you're reading this. It uses the dreaded Write-Host quite a bit, because I wrote it in an early stage of learning PowerShell. Other oddities in the code might also occur!

By default, unless you specify the -Remove parameter, it will simply recursively list empty folders that exist under the specified -Path. It has only been tested against file systems.

You will need to specify the -VerifyNoEmpty parameter or run the script several times to remove nested empty directories. See the examples below.

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 range of use cases.

The front page search engine hits I found for PowerShell scripts for deleting empty folders didn't even consider nested empty directories.

One aspect you need to be aware of, is that if there's a directory you don't have access to list the contents of, it will be treated as empty and an attempt will be made to delete it. This will fail. You might also need to consider the situation where you can't read, but can write/delete. I'm not sure how likely that is though, but I think it's possible. I'm not sure if there is other unforeseen behaviour that results from how I check for empty directories/folders.

## Contents

You can use the script below if you want, but this should also do the trick (at the expense of iterating a lot repeatedly, at every level of nesting, if my brain is working right):

$LogPath = 'C:\temp' # replace this with your root path... Get-ChildItem -LiteralPath$LogPath -Force -Recurse | Where-Object {
$_.PSIsContainer -and  @(Get-ChildItem -LiteralPath$_.Fullname -Force -Recurse | Where { -not $_.PSIsContainer }).Count -eq 0 } | Remove-Item -Recurse -WhatIf  I probably shouldn't mention this, but I've used this technique a couple of times when in a jam, where I take advantage of the fact that cmd.exe's "rd" command (remove directory / rmdir) does not delete non-empty directories by default: PS D:\temp\dirs>$dir = 'foo bar'
PS D:\temp\dirs> md $dir | out-null PS D:\temp\dirs> cmd /c rd$dir
PS D:\temp\dirs> md $dir | out-null PS D:\temp\dirs> 'test' > '.\foo bar\file.txt' PS D:\temp\dirs> cmd /c rd$dir
The directory is not empty.


So you could use this with something like:

Get-ChildItem . | %{ cmd /c rd $_.Name }  Of course, this isn't recursive, and there is no output for successful removal of directories; it just does it. For non-empty directories, you will get the "The directory is not empty" warning. ## Examples A few examples. ### The -VerifyNoEmpty Parameter The parameter -VerifyNoEmpty, together with -Remove, 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 removed 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. The same example as text: PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove -VerifyNoEmpty Iterating 'E:\temp\dirs' 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir1\foo\bar 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir2\baz\boo\mon 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir3\golf -VerifyNoEmpty specified. Found empty dirs on run no 1. Starting next run. Iterating 'E:\temp\dirs' 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir3 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir1\foo 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir2\baz\boo -VerifyNoEmpty specified. Found empty dirs on run no 2. Starting next run. Iterating 'E:\temp\dirs' 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir1 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir2\baz -VerifyNoEmpty specified. Found empty dirs on run no 3. Starting next run. Iterating 'E:\temp\dirs' 12/17/2011 03:35:38: Successfully deleted the empty folder: E:\temp\dirs\dir2 -VerifyNoEmpty specified. Found empty dirs on run no 4. Starting next run. Iterating 'E:\temp\dirs' Made 5 runs in total PS E:\temp\dirs>  ### Multiple Manual Runs Here is an example where the script is run manually several times until there are no empty folders left in the folder structure. PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs E:\temp\dirs\dir1\dir2\dir3 is empty E:\temp\dirs\dir4\dir5\dir6 is empty E:\temp\dirs\dir4\dir5\dir61 is empty E:\temp\dirs\dir4\dir5\dir62 is empty E:\temp\dirs\dir7\dir8\dir9\dir10 is empty # Add the -Remove flag PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove 12/11/2011 09:39:25: Successfully deleted the empty folder: E:\temp\dirs\dir1\dir2\dir3 12/11/2011 09:39:25: Successfully deleted the empty folder: E:\temp\dirs\dir4\dir5\dir6 12/11/2011 09:39:25: Successfully deleted the empty folder: E:\temp\dirs\dir4\dir5\dir61 12/11/2011 09:39:25: Successfully deleted the empty folder: E:\temp\dirs\dir4\dir5\dir62 12/11/2011 09:39:25: Successfully deleted the empty folder: E:\temp\dirs\dir7\dir8\dir9\dir10 # Another run PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove 12/11/2011 09:39:29: Successfully deleted the empty folder: E:\temp\dirs\dir1\dir2 12/11/2011 09:39:29: Successfully deleted the empty folder: E:\temp\dirs\dir7\dir8\dir9 PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove 12/11/2011 09:39:31: Successfully deleted the empty folder: E:\temp\dirs\dir1 12/11/2011 09:39:31: Successfully deleted the empty folder: E:\temp\dirs\dir7\dir8 PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove 12/11/2011 09:39:34: Successfully deleted the empty folder: E:\temp\dirs\dir7 PS E:\temp\dirs> .\Find-Or-Remove-Empty-Dirs.ps1 -Path E:\temp\dirs -Remove PS E:\temp\dirs> dir .\dir4\dir5\dir63\fil.txt Directory: E:\temp\dirs\dir4\dir5\dir63 Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 11.12.2011 09:11 8 fil.txt PS E:\temp\dirs> dir Directory: E:\temp\dirs Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 11.12.2011 09:11 dir4 -a--- 11.12.2011 09:38 3090 Find-Or-Remove-Empty-Dirs.ps1  ## Download ## Source Code <# .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

}
`