Lister tous les fichiers et répertoires dans un répertoire + sous-répertoires


109

Je veux lister tous les fichiers et répertoires contenus dans un répertoire et sous-répertoires de ce répertoire. Si je choisissais C: \ comme répertoire, le programme obtiendrait chaque nom de chaque fichier et dossier du disque dur auquel il avait accès.

Une liste pourrait ressembler à

fd \ 1.txt
fd \ 2.txt
fd \ a \
fd \ b \
fd \ a \ 1.txt
fd \ a \ 2.txt
fd \ a \ a \
fd \ a \ b \
fd \ b \ 1.txt
fd \ b \ 2.txt
fd \ b \ a
fd \ b \ b
fd \ a \ a \ 1.txt
fd \ a \ a \ a \
fd \ a \ b \ 1.txt
fd \ a \ b \ a
fd \ b \ a \ 1.txt
fd \ b \ a \ a \
fd \ b \ b \ 1.txt
fd \ b \ b \ a

Parcourez l'espace de noms System.IO pour les classes et les méthodes qui pourraient vous aider.
Lucero

Consultez cette question et déposez la partie où il correspond à un motif.
dasblinkenlight

Réponses:


192
string[] allfiles = Directory.GetFiles("path/to/dir", "*.*", SearchOption.AllDirectories);

*.*est le modèle pour faire correspondre les fichiers

Si le répertoire est également nécessaire, vous pouvez procéder comme suit:

 foreach (var file in allfiles){
     FileInfo info = new FileInfo(file);
 // Do something with the Folder or just add them to a list via nameoflist.add();
 }

1
Ça ne marchera pas vraiment ... en Lsit<>classe? Que renvoie GetFiles? Et qu'en est-il des noms de répertoires qui ont également été demandés?
Lucero

1
La GetFilesméthode renvoie un tableau de chaînes.
Guffa

en fait ... vous avez raison ... J'apprends Qt il y a environ 2 jours et je me suis un peu trompé
Ruslan F.

Cela peut fonctionner, mais cela échoue souvent avec une exception UnauthorizedAccessException. Comment rechercherait-il uniquement les répertoires auxquels il peut accéder?
derp_in_mouth

cela signifie que dans votre système, cette application n'a pas assez d'autorisations
Ruslan F.

50

Directory.GetFileSystemEntriesexiste dans .NET 4.0+ et renvoie à la fois des fichiers et des répertoires. Appelez ça comme ça:

string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);

Notez qu'il ne fera pas face aux tentatives de lister le contenu des sous-répertoires auxquels vous n'avez pas accès (UnauthorizedAccessException), mais cela peut être suffisant pour vos besoins.


3
C'est de loin la meilleure réponse ici. Il récupère tous les fichiers et dossiers dans une seule ligne de code, ce qu'aucun autre ne fait.
Steve Smith

15

Utilisez les méthodes GetDirectorieset GetFilespour obtenir les dossiers et fichiers.

Utilisez également pour obtenir les dossiers et fichiers dans les sous-dossiers.SearchOption AllDirectories


Utilisez Substring pour couper la partie gauche du nom. :)
Lucero

@Lucero Comment et pourquoi feriez-vous cela? Pathpropose des méthodes plus fiables.
Gusdor

@Gusdor N'hésitez pas à suggérer une manière plus appropriée d'utiliser le Pathpour supprimer une partie gauche fixe du chemin, par exemple `C:` dans l'exemple donné.
Lucero

@Lucero mon commentaire était mal formulé. «Utiliser sous-chaîne» ne me dit pas grand-chose et j'ai dû rester coincé dans linqpad pour trouver une solution intéressante. Par exemple, quel serait le paramètre? Allez-vous faire path.SubString(2)pour supprimer naïvement la lettre de lecteur et les deux points? Que faire si l'annuaire est un partage réseau? Je suggère Pathcomme méthode fiable car elle peut fournir des tas de goodies dans ce domaine. Dans ce cas, vous pouvez écrire filePath.Substring(Path.GetPathRoot(filePath).Length). Oui, cela utilise Substring car c'est le plus concis.
Gusdor

11
public static void DirectorySearch(string dir)
{
    try
    {
        foreach (string f in Directory.GetFiles(dir))
        {
            Console.WriteLine(Path.GetFileName(f));
        }
        foreach (string d in Directory.GetDirectories(dir))
        {
            Console.WriteLine(Path.GetFileName(d));
            DirectorySearch(d);
        }
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

3
Cela améliorerait votre réponse si vous pouviez ajouter une petite explication de ce que fait le code.
Alex

Il parcourt le répertoire de manière récursive et imprime les noms de fichiers ou de répertoires. Pour chaque répertoire interne, il appelle la même fonction. Pour plus d'informations: stackoverflow.com/questions/929276/…
I.Step

3

J'ai peur, la GetFilesméthode renvoie la liste des fichiers mais pas les répertoires. La liste de la question m'invite à dire que le résultat doit également inclure les dossiers. Si vous voulez une liste plus personnalisée, vous pouvez essayer d'appeler GetFileset de GetDirectoriesmanière récursive. Essaye ça:

List<string> AllFiles = new List<string>();
void ParsePath(string path)
{
    string[] SubDirs = Directory.GetDirectories(path);
    AllFiles.AddRange(SubDirs);
    AllFiles.AddRange(Directory.GetFiles(path));
    foreach (string subdir in SubDirs)
        ParsePath(subdir);
}

Conseil: vous pouvez utiliser des classes FileInfoet DirectoryInfosi vous avez besoin de vérifier un attribut spécifique.


2

Une version améliorée avec max lvl pour descendre dans le répertoire et option pour exclure les dossiers:

using System;
using System.IO;

class MainClass {
  public static void Main (string[] args) {

    var dir = @"C:\directory\to\print";
    PrintDirectoryTree(dir, 2, new string[] {"folder3"});
  }


  public static void PrintDirectoryTree(string directory, int lvl, string[] excludedFolders = null, string lvlSeperator = "")
  {
    excludedFolders = excludedFolders ?? new string[0];

    foreach (string f in Directory.GetFiles(directory))
    {
        Console.WriteLine(lvlSeperator+Path.GetFileName(f));
    } 

    foreach (string d in Directory.GetDirectories(directory))
    {
        Console.WriteLine(lvlSeperator + "-" + Path.GetFileName(d));

        if(lvl > 0 && Array.IndexOf(excludedFolders, Path.GetFileName(d)) < 0)
        {
          PrintDirectoryTree(d, lvl-1, excludedFolders, lvlSeperator+"  ");
        }
    }
  }
}

répertoire d'entrée:

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
      file6.txt
  -folder3
    file3.txt
  -folder4
    file4.txt
    file5.txt

sortie de la fonction (le contenu du dossier5 est exclu en raison de la limite lvl et le contenu du dossier3 est exclu car il se trouve dans le tableau des dossiers exclus):

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
  -folder3
  -folder4
    file4.txt
    file5.txt

1

Vous pouvez utiliser FindFirstFile qui renvoie un handle puis caler récursivement une fonction qui appelle FindNextFile.C'est une bonne approche car la structure référencée serait remplie de diverses données telles que alternativeName, lastTmeCreated, modifié, attributs, etc.

Mais lorsque vous utilisez le framework .net, vous devrez entrer dans la zone non gérée.


0

Si vous n'avez pas accès à un sous-dossier dans l'arborescence de répertoires, Directory.GetFiles s'arrête et lève l'exception résultant en une valeur nulle dans la chaîne de réception [].

Ici, voir cette réponse https://stackoverflow.com/a/38959208/6310707

Il gère l'exception à l'intérieur de la boucle et continue de travailler jusqu'à ce que tout le dossier soit parcouru.


0

la manière logique et ordonnée:

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace DirLister
{
class Program
{
    public static void Main(string[] args)
    {
        //with reflection I get the directory from where this program is running, thus listing all files from there and all subdirectories
        string[] st = FindFileDir(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location));
        using ( StreamWriter sw = new StreamWriter("listing.txt", false ) )
        {
            foreach(string s in st)
            {
                //I write what I found in a text file
                sw.WriteLine(s);
            }
        }
    }

    private static string[] FindFileDir(string beginpath)
    {
        List<string> findlist = new List<string>();

        /* I begin a recursion, following the order:
         * - Insert all the files in the current directory with the recursion
         * - Insert all subdirectories in the list and rebegin the recursion from there until the end
         */
        RecurseFind( beginpath, findlist );

        return findlist.ToArray();
    }

    private static void RecurseFind( string path, List<string> list )
    {
        string[] fl = Directory.GetFiles(path);
        string[] dl = Directory.GetDirectories(path);
        if ( fl.Length>0 || dl.Length>0 )
        {
            //I begin with the files, and store all of them in the list
            foreach(string s in fl)
                list.Add(s);
            //I then add the directory and recurse that directory, the process will repeat until there are no more files and directories to recurse
            foreach(string s in dl)
            {
                list.Add(s);
                RecurseFind(s, list);
            }
        }
    }
}
}

Pourriez-vous s'il vous plaît fournir une explication ou des commentaires en ligne, ce que fait votre code?
MarthyM

bien sûr, je l'ai fait, mais cela devrait être explicite, c'est une simple récursivité en boucle dans tous les répertoires et fichiers
Sascha

0

L'exemple suivant, le moyen le plus rapide (non parallélisé) répertorie les fichiers et les sous-dossiers dans une arborescence de répertoires qui gère les exceptions. Il serait plus rapide d'utiliser Directory.EnumerateDirectories à l'aide de SearchOption.AllDirectories pour énumérer tous les répertoires, mais cette méthode échouera si elle rencontre une exception UnauthorizedAccessException ou PathTooLongException.

Utilise le type de collection Stack générique, qui est une pile dernier entré, premier sorti (LIFO) et n'utilise pas de récursivité. Depuis https://msdn.microsoft.com/en-us/library/bb513869.aspx , vous permet d'énumérer tous les sous-répertoires et fichiers et de traiter efficacement ces exceptions.

    public class StackBasedIteration
{
    static void Main(string[] args)
    {
        // Specify the starting folder on the command line, or in 
        // Visual Studio in the Project > Properties > Debug pane.
        TraverseTree(args[0]);

        Console.WriteLine("Press any key");
        Console.ReadKey();
    }

    public static void TraverseTree(string root)
    {
        // Data structure to hold names of subfolders to be
        // examined for files.
        Stack<string> dirs = new Stack<string>(20);

        if (!System.IO.Directory.Exists(root))
        {
            throw new ArgumentException();
        }
        dirs.Push(root);

        while (dirs.Count > 0)
        {
            string currentDir = dirs.Pop();
            string[] subDirs;
            try
            {
                subDirs = System.IO.Directory.EnumerateDirectories(currentDir); //TopDirectoryOnly
            }
            // An UnauthorizedAccessException exception will be thrown if we do not have
            // discovery permission on a folder or file. It may or may not be acceptable 
            // to ignore the exception and continue enumerating the remaining files and 
            // folders. It is also possible (but unlikely) that a DirectoryNotFound exception 
            // will be raised. This will happen if currentDir has been deleted by
            // another application or thread after our call to Directory.Exists. The 
            // choice of which exceptions to catch depends entirely on the specific task 
            // you are intending to perform and also on how much you know with certainty 
            // about the systems on which this code will run.
            catch (UnauthorizedAccessException e)
            {                    
                Console.WriteLine(e.Message);
                continue;
            }
            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }

            string[] files = null;
            try
            {
                files = System.IO.Directory.EnumerateFiles(currentDir);
            }

            catch (UnauthorizedAccessException e)
            {

                Console.WriteLine(e.Message);
                continue;
            }

            catch (System.IO.DirectoryNotFoundException e)
            {
                Console.WriteLine(e.Message);
                continue;
            }
            // Perform the required action on each file here.
            // Modify this block to perform your required task.
            foreach (string file in files)
            {
                try
                {
                    // Perform whatever action is required in your scenario.
                    System.IO.FileInfo fi = new System.IO.FileInfo(file);
                    Console.WriteLine("{0}: {1}, {2}", fi.Name, fi.Length, fi.CreationTime);
                }
                catch (System.IO.FileNotFoundException e)
                {
                    // If file was deleted by a separate application
                    //  or thread since the call to TraverseTree()
                    // then just continue.
                    Console.WriteLine(e.Message);
                    continue;
                }
                catch (UnauthorizedAccessException e)
                {                    
                    Console.WriteLine(e.Message);
                    continue;
                }
            }

            // Push the subdirectories onto the stack for traversal.
            // This could also be done before handing the files.
            foreach (string str in subDirs)
                dirs.Push(str);
        }
    }
}

Vous utilisez des tâches pour un grand nombre de fichiers et de répertoires?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx est la version Parallel Threading de la solution ci-dessus utilisant une collection de pile et plus rapide.
Markus

0

J'utilise le code suivant avec un formulaire qui a 2 boutons, un pour quitter et l'autre pour démarrer. Une boîte de dialogue de navigateur de dossier et une boîte de dialogue d'enregistrement de fichier. Le code est répertorié ci-dessous et fonctionne sur mon système Windows10 (64):

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Directory_List
{

    public partial class Form1 : Form
    {
        public string MyPath = "";
        public string MyFileName = "";
        public string str = "";

        public Form1()
        {
            InitializeComponent();
        }    
        private void cmdQuit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }    
        private void cmdGetDirectory_Click(object sender, EventArgs e)
        {
            folderBrowserDialog1.ShowDialog();
            MyPath = folderBrowserDialog1.SelectedPath;    
            saveFileDialog1.ShowDialog();
            MyFileName = saveFileDialog1.FileName;    
            str = "Folder = " + MyPath + "\r\n\r\n\r\n";    
            DirectorySearch(MyPath);    
            var result = MessageBox.Show("Directory saved to Disk!", "", MessageBoxButtons.OK);
                Application.Exit();    
        }    
        public void DirectorySearch(string dir)
        {
                try
            {
                foreach (string f in Directory.GetFiles(dir))
                {
                    str = str + dir + "\\" + (Path.GetFileName(f)) + "\r\n";
                }    
                foreach (string d in Directory.GetDirectories(dir, "*"))
                {

                    DirectorySearch(d);
                }
                        System.IO.File.WriteAllText(MyFileName, str);

            }
            catch (System.Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

0

Avec cela, vous pouvez simplement les exécuter et choisir le sous-dossier lorsque la console est exécutée

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using data.Patcher; // The patcher XML
namespace PatchBuilder
{
class Program
{
    static void Main(string[] args)
    {
        string patchDir;
        if (args.Length == 0)
        {
            Console.WriteLine("Give the patch directory in argument");
            patchDir = Console.ReadLine();
        }
        else
        {
            patchDir = args[0];
        }

        if (File.Exists(Path.Combine(patchDir, "patch.xml")))
            File.Delete(Path.Combine(patchDir, "patch.xml"));

        var files = Directory.EnumerateFiles(patchDir, "*", SearchOption.AllDirectories).OrderBy(p => p).ToList();

        foreach (var file in files.Where(file => file.StartsWith("patch\\Resources")).ToArray())
        {
            files.Remove(file);
            files.Add(file);
        }

        var tasks = new List<MetaFileEntry>();
        using (var md5Hasher = MD5.Create())
        {
            for (int i = 0; i < files.Count; i++)
            {
                var file = files[i];

                if ((File.GetAttributes(file) & FileAttributes.Hidden) != 0)
                    continue;

                var content = File.ReadAllBytes(file);
                var md5Hasher2 = MD5.Create();

                var task =
                    new MetaFileEntry
                    {
                        LocalURL = GetRelativePath(file, patchDir + "\\"),
                        RelativeURL = GetRelativePath(file, patchDir + "\\"),
                        FileMD5 = Convert.ToBase64String(md5Hasher2.ComputeHash(content)),
                        FileSize = content.Length,
                    };

                md5Hasher2.Dispose();

                var pathBytes = Encoding.UTF8.GetBytes(task.LocalURL.ToLower());
                md5Hasher.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0);
                if (i == files.Count - 1)
                    md5Hasher.TransformFinalBlock(content, 0, content.Length);
                else
                    md5Hasher.TransformBlock(content, 0, content.Length, content, 0);

                tasks.Add(task);
                Console.WriteLine(@"Add " + task.RelativeURL);
            }

            var patch = new MetaFile
            {
                Tasks = tasks.ToArray(),
                FolderChecksum = BitConverter.ToString(md5Hasher.Hash).Replace("-", "").ToLower(),
            };


            //XmlUtils.Serialize(Path.Combine(patchDir, "patch.xml"), patch);
            Console.WriteLine(@"Created Patch in {0} !", Path.Combine(patchDir, "patch.xml"));
        }

        Console.Read();
    }

    static string GetRelativePath(string fullPath, string relativeTo)
    {
        var foldersSplitted = fullPath.Split(new[] { relativeTo.Replace("/", "\\").Replace("\\\\", "\\") }, StringSplitOptions.RemoveEmptyEntries); // cut the source path and the "rest" of the path

        return foldersSplitted.Length > 0 ? foldersSplitted.Last() : ""; // return the "rest"
    }
}
}

et c'est le patchar pour l'exportation XML

using System.Xml.Serialization;

namespace data.Patcher
{
    public class MetaFile
    {

        [XmlArray("Tasks")]
        public MetaFileEntry[] Tasks
        {
            get;
            set;
        }

        [XmlAttribute("checksum")]
        public string FolderChecksum
        {
            get;
            set;
        }
    }
}

-1
using System.IO;
using System.Text;
string[] filePaths = Directory.GetFiles(@"path", "*.*", SearchOption.AllDirectories);

Votre réponse n'ajoute rien de nouveau à une réponse déjà votée la plus populaire.
locale par défaut le

1
C'est également faux, car cela ne renvoie aucun répertoire (comme la question le précise), uniquement des fichiers réels.
Alastair Maw

-1

Un peu simple et lentement mais qui fonctionne !! si vous ne donnez pas de chemin de fichier, utilisez essentiellement le "fixPath", ce n'est qu'un exemple .... vous pouvez rechercher le type de fichier correct ce que vous voulez, j'ai fait une erreur lorsque j'ai choisi le nom de la liste car le "temporaireFileList est la liste de fichiers recherchée alors continuez ... et la "errorList" parle d'elle-même

 static public void Search(string path, string fileType, List<string> temporaryFileList, List<string> errorList)
    {

        List<string> temporaryDirectories = new List<string>();

        //string fix = @"C:\Users\" + Environment.UserName + @"\";
        string fix = @"C:\";
        string folders = "";
        //Alap útvonal megadása 
        if (path.Length != 0)
        { folders = path; }
        else { path = fix; }

        int j = 0;
        int equals = 0;
        bool end = true;

        do
        {

            equals = j;
            int k = 0;

            try
            {

                int foldersNumber = 
                Directory.GetDirectories(folders).Count();
                int fileNumber = Directory.GetFiles(folders).Count();

                if ((foldersNumber != 0 || fileNumber != 0) && equals == j)
                {

                    for (int i = k; k < 
                    Directory.GetDirectories(folders).Length;)
                    {

             temporaryDirectories.Add(Directory.GetDirectories(folders)[k]);
                        k++;
                    }

                    if (temporaryDirectories.Count == j)
                    {
                        end = false;
                        break;
                    }
                    foreach (string files in Directory.GetFiles(folders))
                    {
                        if (files != string.Empty)
                        {
                            if (fileType.Length == 0)
                            {
                                temporaryDirectories.Add(files);
                            }
                            else
                            {

                                if (files.Contains(fileType))
                                {
                                    temporaryDirectories.Add(files);

                                }
                            }
                        }
                        else
                        {
                            break;
                        }
                    }

                }

                equals++;

                for (int i = j; i < temporaryDirectories.Count;)
                {
                    folders = temporaryDirectories[i];
                    j++;
                    break;
                }

            }
            catch (Exception ex)
            {
                errorList.Add(folders);

                for (int i = j; i < temporaryDirectories.Count;)
                {
                    folders = temporaryDirectories[i];
                    j++;
                    break;
                }
            }
        } while (end);
    }

-1

Créer une liste de chaînes

    public static List<string> HTMLFiles = new List<string>();

 private void Form1_Load(object sender, EventArgs e)
        {

     HTMLFiles.AddRange(Directory.GetFiles(@"C:\DataBase", "*.txt"));
            foreach (var item in HTMLFiles)
            {
                MessageBox.Show(item);
            }

}

Cela n'obtient pas de sous-répertoires.
TidyDev
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.