c# - obtener - Buscando archivos en directorios recursivamente
obtener ruta de carpeta c# (9)
Tengo el siguiente código para buscar recursivamente archivos a través de un directorio, que me devuelve una lista de todos los archivos xml. Todo funciona bien, excepto que los archivos xml en el directorio raíz no están incluidos en la lista.
Entiendo por qué, ya que lo primero que hace es obtener los directorios en la raíz, luego obtener los archivos, por lo tanto, falta la llamada a GetFiles () en la raíz. Intenté incluir la llamada a GetFiles () antes del foreach, pero los resultados no son los que esperaba.
public static ArrayList DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
fileList.Add(f);
}
}
DirSearch(d);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return fileList;
}
Mi estructura de directorio es algo así como:
RootDirectory
test1.0.xml
test1.1.xml
test1.2.xml
2ndLevDir
test2.0.xml
test2.1.xml
3rdLevDir
test3.0.xml
test3.1.xml
Código de devoluciones:
test2.0.xml
test2.1.xml
test3.0.xml
test3.1.xml
Me gustaría devolver cada archivo, incluyendo:
test1.0.xml
test1.1.xml
test1.2.xml
No muy bien verso con recursividad. Cualquier puntero sería muy apreciado.
Deberá mover el ciclo de los archivos fuera del ciclo para las carpetas. Además, deberá pasar la estructura de datos que contiene la colección de archivos a cada llamada del método. De esa forma, todos los archivos entran en una sola lista.
public static List<string> DirSearch(string sDir, List<string> files)
{
foreach (string f in Directory.GetFiles(sDir, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
files.Add(f);
}
}
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch(d, files);
}
return files;
}
Entonces llámalo así.
List<string> files = DirSearch("c:/foo", new List<string>());
Actualizar:
Bien, sin que yo sepa, hasta que lea la otra respuesta de todos modos, ya hay un mecanismo incorporado para hacer esto. Dejaré mi respuesta en caso de que esté interesado en ver cómo se debe modificar su código para que funcione.
Debería tener el ciclo sobre los archivos antes o después del ciclo sobre los directorios, pero no anidados dentro de él como lo ha hecho.
foreach (string f in Directory.GetFiles(d, "*.xml"))
{
string extension = Path.GetExtension(f);
if (extension != null && (extension.Equals(".xml")))
{
fileList.Add(f);
}
}
foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch(d);
}
Está creando tres listas, en lugar de usar una (no usa el valor de retorno de DirSearch(d)
). Puede usar una lista como parámetro para guardar el estado:
static void Main(string[] args)
{
var list = new List<string>();
DirSearch(list, ".");
foreach (var file in list)
{
Console.WriteLine(file);
}
}
public static void DirSearch(List<string> files, string startDirectory)
{
try
{
foreach (string file in Directory.GetFiles(startDirectory, "*.*"))
{
string extension = Path.GetExtension(file);
if (extension != null)
{
files.Add(file);
}
}
foreach (string directory in Directory.GetDirectories(startDirectory))
{
DirSearch(files, directory);
}
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
}
}
Esto devuelve todos los archivos xml recursivamente:
var allFiles = Directory.GetFiles(path, "*.xml", SearchOption.AllDirectories);
Para fines de búsqueda de archivos y directorios, me gustaría ofrecer el uso de la biblioteca especializada .NET de subprocesos múltiples que posee amplias oportunidades de búsqueda y funciona muy rápido.
Toda la información sobre la biblioteca que puede encontrar en GitHub: https://github.com/VladPVS/FastSearchLibrary
Si desea descargarlo, puede hacerlo aquí: https://github.com/VladPVS/FastSearchLibrary/releases
Si tienes alguna pregunta, pregúntales.
Es un ejemplo demostrativo de cómo puedes usarlo:
class Searcher
{
private static object locker = new object();
private FileSearcher searcher;
List<FileInfo> files;
public Searcher()
{
files = new List<FileInfo>(); // create list that will contain search result
}
public void Startsearch()
{
CancellationTokenSource tokenSource = new CancellationTokenSource();
// create tokenSource to get stop search process possibility
searcher = new FileSearcher(@"C:/", (f) =>
{
return Regex.IsMatch(f.Name, @".*[Dd]ragon.*.jpg$");
}, tokenSource); // give tokenSource in constructor
searcher.FilesFound += (sender, arg) => // subscribe on FilesFound event
{
lock (locker) // using a lock is obligatorily
{
arg.Files.ForEach((f) =>
{
files.Add(f); // add the next received file to the search results list
Console.WriteLine($"File location: {f.FullName}, /nCreation.Time: {f.CreationTime}");
});
if (files.Count >= 10) // one can choose any stopping condition
searcher.StopSearch();
}
};
searcher.SearchCompleted += (sender, arg) => // subscribe on SearchCompleted event
{
if (arg.IsCanceled) // check whether StopSearch() called
Console.WriteLine("Search stopped.");
else
Console.WriteLine("Search completed.");
Console.WriteLine($"Quantity of files: {files.Count}"); // show amount of finding files
};
searcher.StartSearchAsync();
// start search process as an asynchronous operation that doesn''t block the called thread
}
}
Pruebe el siguiente método:
public static IEnumerable<string> GetXMLFiles(string directory)
{
List<string> files = new List<string>();
try
{
files.AddRange(Directory.GetFiles(directory, "*.xml", SearchOption.AllDirectories));
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return files;
}
Puede usar esta sobrecarga de Directory.GetFiles
que busca subdirectorios por usted.
Usando EnumerateFiles para obtener archivos en directorios anidados. Utilice AllDirectories para recurse a través de directorios.
using System;
using System.IO;
class Program
{
static void Main()
{
// Call EnumerateFiles in a foreach-loop.
foreach (string file in Directory.EnumerateFiles(@"c:/files",
"*.xml",
SearchOption.AllDirectories))
{
// Display file path.
Console.WriteLine(file);
}
}
}
puedes hacer algo como esto:
foreach (var file in Directory.GetFiles(MyFolder, "*.xml", SearchOption.AllDirectories))
{
// do something with this file
}