vacío uso una net limpiar liberar fichero está eliminar directorio desde como carpetas carpeta asp archivos archivo c# .net subdirectories

uso - C#Eliminar todos los subdirectorios vacíos



eliminar una carpeta desde c# (8)

Tengo una tarea para limpiar una gran cantidad de directorios. Quiero comenzar en un directorio y eliminar cualquier subdirectorio (sin importar la profundidad) que no contenga archivos (los archivos nunca serán eliminados, solo los directorios). El directorio inicial se eliminará si no contiene archivos o subdirectorios. Esperaba que alguien me indicara algún código existente para esto en lugar de tener que reinventar la rueda. Haré esto usando C #.


Aquí hay una versión que aprovecha la ejecución paralela para hacerlo más rápido en algunos casos:

public static void DeleteEmptySubdirectories(string parentDirectory){ System.Threading.Tasks.Parallel.ForEach(System.IO.Directory.GetDirectories(parentDirectory), directory => { DeleteEmptySubdirectories(directory); if(!System.IO.Directory.EnumerateFileSystemEntries(directory).Any()) System.IO.Directory.Delete(directory, false); }); }

Este es el mismo código en modo de un solo hilo:

public static void DeleteEmptySubdirectoriesSingleThread(string parentDirectory){ foreach(string directory in System.IO.Directory.GetDirectories(parentDirectory)){ DeleteEmptySubdirectories(directory); if(!System.IO.Directory.EnumerateFileSystemEntries(directory).Any()) System.IO.Directory.Delete(directory, false); } }

... y aquí hay un código de muestra que podría usar para evaluar los resultados en su escenario:

var stopWatch = new System.Diagnostics.Stopwatch(); for(int i = 0; i < 100; i++) { stopWatch.Restart(); DeleteEmptySubdirectories(rootPath); stopWatch.Stop(); StatusOutputStream.WriteLine("Parallel: "+stopWatch.ElapsedMilliseconds); stopWatch.Restart(); DeleteEmptySubdirectoriesSingleThread(rootPath); stopWatch.Stop(); StatusOutputStream.WriteLine("Single: "+stopWatch.ElapsedMilliseconds); }

... y aquí hay algunos resultados de mi máquina para un directorio compartido en una red de área amplia. Actualmente, este recurso compartido solo tiene 16 subcarpetas y 2277 archivos.

Parallel: 1479 Single: 4724 Parallel: 1691 Single: 5603 Parallel: 1540 Single: 4959 Parallel: 1592 Single: 4792 Parallel: 1671 Single: 4849 Parallel: 1485 Single: 4389


Desde aquí, secuencia de comandos Powershell para eliminar directorios vacíos :

$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 } }

Nota : ¡use bajo su propio riesgo!


Ejecutar la prueba en C: / Windows 1000 veces en los 3 métodos mencionados hasta ahora produjo esto:

GetFiles+GetDirectories:630ms GetFileSystemEntries:295ms EnumerateFileSystemEntries.Any:71ms

Ejecutarlo en una carpeta vacía arrojó esto (1000 veces más):

GetFiles+GetDirectories:131ms GetFileSystemEntries:66ms EnumerateFileSystemEntries.Any:64ms

Así que EnumerateFileSystemEntries es de lejos el mejor en general cuando se buscan carpetas vacías.


Si confía en DirectoryInfo.Delete solo eliminando directorios vacíos, puede escribir un método de extensión sucinto

public static void DeleteEmptyDirs(this DirectoryInfo dir) { foreach (DirectoryInfo d in dir.GetDirectories()) d.DeleteEmptyDirs(); try { dir.Delete(); } catch (IOException) {} catch (UnauthorizedAccessException) {} }

Uso:

static void Main() { new DirectoryInfo(@"C:/temp").DeleteEmptyDirs(); }


Si puede orientar el .NET 4.0, puede usar los nuevos métodos en la clase del Directory para enumerar los directorios para no pagar una penalización de rendimiento al listar cada archivo en un directorio cuando solo desea saber si hay al menos uno.

Los métodos son:

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

Una posible implementación usando recursión:

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) { } }

También mencionas que el árbol de directorios podría ser muy profundo, por lo que es posible que obtengas algunas excepciones si la ruta que estás explorando es demasiado larga.


Usando C # Code.

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); } } }


private static void deleteEmptySubFolders(string ffd, bool deleteIfFileSizeZero=false) { DirectoryInfo di = new DirectoryInfo(ffd); foreach (DirectoryInfo diSon in di.GetDirectories("*", SearchOption.TopDirectoryOnly)) { FileInfo[] fis = diSon.GetFiles("*.*", SearchOption.AllDirectories); if (fis == null || fis.Length < 1) { diSon.Delete(true); } else { if (deleteIfFileSizeZero) { long total = 0; foreach (FileInfo fi in fis) { total = total + fi.Length; if (total > 0) { break; } } if (total == 0) { diSon.Delete(true); continue; } } deleteEmptySubFolders(diSon.FullName, deleteIfFileSizeZero); } } }


//Recursive scan of empty dirs. See example output bottom string startDir = @"d:/root"; void Scan(string dir, bool stepBack) { //directory not empty if (Directory.GetFileSystemEntries(dir).Length > 0) { if (!stepBack) { foreach (string subdir in Directory.GetDirectories(dir)) Scan(subdir, false); } } //directory empty so delete it. else { Directory.Delete(dir); string prevDir = dir.Substring(0, dir.LastIndexOf("//")); if (startDir.Length <= prevDir.Length) Scan(prevDir, true); } } //call like this Scan(startDir, false); /*EXAMPLE outputof d:/root with empty subfolders and one filled with files Scanning d:/root Scanning d:/root/folder1 (not empty) Scanning d:/root/folder1/folder1sub1 (not empty) Scanning d:/root/folder1/folder1sub1/folder2sub2 (deleted!) Scanning d:/root/folder1/folder1sub1 (deleted!) Scanning d:/root/folder1 (deleted) Scanning d:/root (not empty) Scanning d:/root/folder2 (not empty) Scanning d:/root/folder2/folder2sub1 (deleted) Scanning d:/root/folder2 (not empty) Scanning d:/root/folder2/notempty (not empty) */