Comment lister récursivement tous les fichiers d'un répertoire et des répertoires enfants en C# ?
Réponses
Trop de publicités?Notez que dans .NET 4.0, des fonctions de fichiers basées sur des itérateurs (plutôt que sur des tableaux) sont (soi-disant) intégrées :
foreach (string file in Directory.EnumerateFiles(
path, "*.*", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
Pour l'instant, j'utiliserais quelque chose comme ci-dessous ; la méthode récursive intégrée se brise trop facilement si vous n'avez pas accès à un seul sous-répertoire... ; la fonction Queue<string>
évite une trop grande récursion dans la pile d'appels, et le bloc d'itérateurs nous évite d'avoir un énorme tableau.
static void Main() {
foreach (string file in GetFiles(SOME_PATH)) {
Console.WriteLine(file);
}
}
static IEnumerable<string> GetFiles(string path) {
Queue<string> queue = new Queue<string>();
queue.Enqueue(path);
while (queue.Count > 0) {
path = queue.Dequeue();
try {
foreach (string subDir in Directory.GetDirectories(path)) {
queue.Enqueue(subDir);
}
}
catch(Exception ex) {
Console.Error.WriteLine(ex);
}
string[] files = null;
try {
files = Directory.GetFiles(path);
}
catch (Exception ex) {
Console.Error.WriteLine(ex);
}
if (files != null) {
for(int i = 0 ; i < files.Length ; i++) {
yield return files[i];
}
}
}
}
Ce site L'article couvre tout ce dont vous avez besoin. Sauf qu'au lieu de chercher dans les fichiers et de comparer les noms, il suffit d'imprimer les noms.
Il peut être modifié comme suit :
static void DirSearch(string sDir)
{
try
{
foreach (string d in Directory.GetDirectories(sDir))
{
foreach (string f in Directory.GetFiles(d))
{
Console.WriteLine(f);
}
DirSearch(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}
Dans .NET 4.5, au moins, il y a cette version qui est beaucoup plus courte et qui a le bonus supplémentaire d'évaluer tout critère de fichier pour l'inclusion dans la liste :
/// </remarks>
public static IEnumerable<string> GetAllFiles(string path, Func<FileInfo, bool> checkFile = null)
{
string mask = Path.GetFileName(path);
if (string.IsNullOrEmpty(mask))
mask = "*.*";
path = Path.GetDirectoryName(path);
string[] files = Directory.GetFiles(path, mask, SearchOption.AllDirectories);
foreach (string file in files)
{
if (checkFile == null || checkFile(new FileInfo(file)))
yield return file;
}
}
Utilisez comme :
string folder = Config.TestInput();
string mask = folder + "*.*";
var list = UT.GetAllFiles(mask, (info) => Path.GetExtension(info.Name) == ".html").ToList();
Assert.AreNotEqual(0, list.Count);
var lastQuarter = DateTime.Now.AddMonths(-3);
list = UT.GetAllFiles(mask, (info) => info.CreationTime >= lastQuarter).ToList();
Assert.AreNotEqual(0, list.Count);
D'excellentes réponses, mais ces réponses n'ont pas résolu mon problème.
Dès qu'un problème de permission de dossier se pose : "Permission refusée", le code échoue. Voici ce que j'ai utilisé pour contourner le problème de "Permission refusée" :
private int counter = 0;
private string[] MyDirectories = Directory.GetDirectories("C:\\");
private void ScanButton_Click(object sender, EventArgs e)
{
Thread MonitorSpeech = new Thread(() => ScanFiles());
MonitorSpeech.Start();
}
private void ScanFiles()
{
string CurrentDirectory = string.Empty;
while (counter < MyDirectories.Length)
{
try
{
GetDirectories();
CurrentDirectory = MyDirectories[counter++];
}
catch
{
if (!this.IsDisposed)
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + CurrentDirectory); });
}
}
}
}
private void GetDirectories()
{
foreach (string directory in MyDirectories)
{
GetFiles(directory);
}
}
private void GetFiles(string directory)
{
try
{
foreach (string file in Directory.GetFiles(directory, "*"))
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add(file); });
}
}
catch
{
listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + directory); });
}
}
J'espère que cela aidera d'autres personnes.
- Réponses précédentes
- Plus de réponses