tags:

views:

260

answers:

3

I have a task to clean up a large number of directories. I want to start at a directory and delete any sub-directories (no matter how deep) that contain no files (files will never be deleted, only directories). The starting directory will then be deleted if it contains no files or subdirectories. I was hoping someone could point me to some existing code for this rather than having to reinvent the wheel. I will be doing this using C#.

+3  A: 

From here, Powershell script to remove empty directories:

$items = Get-ChildItem -Recurse

foreach($item in $items)
{
      if( $item.PSIsContainer )
      {
            $subitems = Get-ChildItem -Recurse -Path $item.FullName
            if($subitems -eq $null)
            {
                  "Remove item: " + $item.FullName
                  Remove-Item $item.FullName
            }
            $subitems = $null
      }
}

Note: use at own risk!

Mitch Wheat
Powershell is not an option, sorry. Thanks though.
Jay
+6  A: 

In C#:

       static void Main(string[] args)
    {
        processDirectory(@"c:\temp");
    }

    private static void processDirectory(string startLocation)
    {
        foreach (var directory in Directory.GetDirectories(startLocation))
        {
            processDirectory(directory);
            if (Directory.GetFiles(directory).Length == 0 && Directory.GetDirectories(directory).Length == 0)
            {
                Directory.Delete(directory, false);
            }
        }
    }
Ragoczy
Thank you very much, exactly what I was looking for.
Jay
A quicker way of writing your `if` statement could be `if (Directory.GetFileSystemEntries(directory).Length == 0)`
Jesse C. Slicer
+3  A: 

If you can target the .NET 4.0 you can use the new methods on the Directory class to enumerate the directories in order to not pay a performance penalty in listing every file in a directory when you just want to know if there is at least one.

The methods are:

  • Directory.EnumerateDirectories
  • Directory.EnumerateFiles
  • Directory.EnumerateFileSystemEntries

A possible implementation using recursion:

static void Main(string[] args)
{
    DeleteEmptyDirs("Start");
}

static void DeleteEmptyDirs(string dir)
{
    if (String.IsNullOrEmpty(dir))
        throw new ArgumentException(
            "Starting directory is a null reference or an empty string", 
            "dir");

    try
    {
        foreach (var d in Directory.EnumerateDirectories(dir))
        {
            DeleteEmptyDirs(d);
        }

        var entries = Directory.EnumerateFileSystemEntries(dir);

        if (!entries.Any())
        {
            try
            {
                Directory.Delete(dir);
            }
            catch (UnauthorizedAccessException) { }
            catch (DirectoryNotFoundException) { }
        }
    }
    catch (UnauthorizedAccessException) { }
}

You also mention that the directory tree could be very deep so it's possible you might get some exceptions if the path you are probing are too long.

João Angelo
Thanks, but unfortunately we don't use .Net 4.0. I wish we could as I have about 20,000 folders to process.
Jay
Nice answer. Instead of `if (String.IsNullOrEmpty(entries.FirstOrDefault()))`, you could also use `if ( ! entries.Any() )`, which is a bit cleaner IMHO.
Danko Durbić
@Danko Durbić, completely agree with you, I didn't notice the overload without parameters and was already asking myself why `Enumerable` didn't have something to quickly check for an empty `IEnumerable`. Thanks, I updated the answer.
João Angelo