365 votes

Comment lister récursivement tous les fichiers d'un répertoire en C# ?

Comment lister récursivement tous les fichiers d'un répertoire et des répertoires enfants en C# ?

481voto

Marc Gravell Points 482669

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

219voto

John T Points 14067

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

127voto

Pescuma Points 94
Directory.GetFiles("C:\\", "*.*", SearchOption.AllDirectories)

14voto

John Kaster Points 912

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

3voto

Chris Points 360

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.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X