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
2010-05-11 14:28:55
Powershell is not an option, sorry. Thanks though.
Jay
2010-05-11 14:40:05
+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
2010-05-11 14:44:32
A quicker way of writing your `if` statement could be `if (Directory.GetFileSystemEntries(directory).Length == 0)`
Jesse C. Slicer
2010-05-11 15:36:26
+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.EnumerateDirectoriesDirectory.EnumerateFilesDirectory.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
2010-05-11 14:55:12
Thanks, but unfortunately we don't use .Net 4.0. I wish we could as I have about 20,000 folders to process.
Jay
2010-05-11 14:58:34
Nice answer. Instead of `if (String.IsNullOrEmpty(entries.FirstOrDefault()))`, you could also use `if ( ! entries.Any() )`, which is a bit cleaner IMHO.
Danko Durbić
2010-05-11 15:06:34
@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
2010-05-11 15:40:54