PowerShell script to recursively delete empty folders

From Svendsen Tech Powershell Wiki
Jump to: navigation, search

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.

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






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.

Find-Or-Remove-Empty-Dirs-VerifyNoEmpty-Run-Screenshot.png

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
    
}
Personal tools