Elenca tutti i file e le directory in una directory + sottodirectory


109

Voglio elencare tutti i file e le directory contenuti in una directory e nelle sottodirectory di quella directory. Se scegliessi C: \ come directory, il programma otterrebbe tutti i nomi di ogni file e cartella sul disco rigido a cui aveva accesso.

Potrebbe apparire un elenco

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

Sfoglia lo spazio dei nomi System.IO per classi e metodi che potrebbero aiutarti.
Lucero

Dai un'occhiata a questa domanda e rilascia la parte in cui sta abbinando uno schema.
dasblinkenlight

Risposte:


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

dove *.*è il modello per abbinare i file

Se è necessaria anche la directory, puoi procedere in questo modo:

 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
Non funzionerà davvero ... Lsit<>classe? Cosa restituisce GetFiles? E i nomi delle directory che sono stati anche richiesti?
Lucero

1
Il GetFilesmetodo restituisce una matrice di stringhe.
Guffa

in realtà ... hai ragione ... sto imparando Qt circa 2 giorni fa e mi sono sbagliato un po '
Ruslan F.

Potrebbe funzionare, ma spesso non riesce con una UnauthorizedAccessException. Come farebbe la ricerca solo nelle directory a cui può accedere?
derp_in_mouth

significa che nel tuo sistema questa app non ha abbastanza autorizzazioni
Ruslan F.

50

Directory.GetFileSystemEntriesesiste in .NET 4.0+ e restituisce sia file che directory. Chiamalo così:

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

Nota che non farà fronte ai tentativi di elencare i contenuti delle sottodirectory a cui non hai accesso (UnauthorizedAccessException), ma potrebbe essere sufficiente per le tue esigenze.


3
Questa è di gran lunga la migliore risposta qui. Ottiene tutti i file e le cartelle in una riga di codice, cosa che nessuno degli altri fa.
Steve Smith

15

Usa la GetDirectorieseGetFiles metodi per ottenere cartelle e file.

Utilizzare il per ottenere anche le cartelle ei file nelle sottocartelle.SearchOption AllDirectories


Usa Sottostringa per tagliare la parte sinistra del nome. :)
Lucero

@Lucero Come e perché lo faresti? Pathoffre metodi più affidabili.
Gusdor

@Gusdor Sentiti libero di suggerire un modo più adatto utilizzando il Pathper rimuovere una parte sinistra fissa del percorso, ad esempio "C:" nell'esempio fornito.
Lucero

@ Lucero il mio commento è stato mal formulato. 'Usa sottostringa' non mi dice molto e ho dovuto rimanere bloccato in linqpad per ottenere una buona soluzione. Ad esempio, quale sarebbe il parametro? Hai intenzione di path.SubString(2)rimuovere ingenuamente lettera di unità e due punti? E se la directory fosse una condivisione di rete? Suggerisco Pathcome metodo affidabile perché può fornire un sacco di chicche in questo settore. In questo caso, puoi scrivere filePath.Substring(Path.GetPathRoot(filePath).Length). Sì, utilizza la sottostringa in quanto è la più concisa.
Gusdor

10
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
Migliorerebbe la tua risposta se puoi aggiungere una piccola spiegazione di ciò che fa il codice.
Alex

Passa ricorsivamente attraverso la directory e stampa i nomi dei file o delle directory. Per ogni directory interna chiama la stessa funzione. Per maggiori informazioni: stackoverflow.com/questions/929276/...
I.Step

3

Temo che il GetFilesmetodo restituisca l'elenco dei file ma non le directory. L'elenco nella domanda mi suggerisce che il risultato dovrebbe includere anche le cartelle. Se desideri un elenco più personalizzato, puoi provare a chiamare GetFilese in GetDirectoriesmodo ricorsivo. Prova questo:

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

Suggerimento: puoi usare FileInfoe DirectoryInfoclasses se devi controllare un attributo specifico.


1

È possibile utilizzare FindFirstFile che restituisce un handle e quindi cal ricorsivamente una funzione che chiama FindNextFile.Questo è un buon approccio in quanto la struttura a cui si fa riferimento sarebbe riempita con vari dati come alternativeName, lastTmeCreated, modificati, attributi ecc.

Ma quando usi .net framework, dovresti entrare nell'area non gestita.


1

Alcune versioni migliorate con max lvl per scendere nella directory e opzione per escludere le cartelle:

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

directory di input:

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

output della funzione (il contenuto della cartella5 è escluso a causa del limite lvl e il contenuto della cartella3 è escluso perché è nell'array excludedFolders):

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

0

Se non si ha accesso a una sottocartella all'interno della struttura della directory, Directory.GetFiles si interrompe e genera l'eccezione risultante in un valore nullo nella stringa di ricezione [].

Qui, vedi questa risposta https://stackoverflow.com/a/38959208/6310707

Gestisce l'eccezione all'interno del ciclo e continua a lavorare fino a quando l'intera cartella non viene attraversata.


0

il modo logico e ordinato:

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

Potresti fornire una spiegazione o commenti in linea, cosa fa il tuo codice?
MarthyM

certo, l'ho fatto, ma dovrebbe essere autoesplicativo, è una semplice ricorsione in ciclo attraverso tutte le directory e i file
Sascha

0

Il seguente esempio è il più veloce (non parallelizzato) elenca i file e le sottocartelle in un albero di directory che gestisce le eccezioni. Sarebbe più veloce usare Directory.EnumerateDirectories usando SearchOption.AllDirectories per enumerare tutte le directory, ma questo metodo fallirà se colpisce una UnauthorizedAccessException o PathTooLongException.

Utilizza il tipo di raccolta Stack generico, che è uno stack LIFO (last in first out) e non utilizza la ricorsione. Da https://msdn.microsoft.com/en-us/library/bb513869.aspx , consente di enumerare tutte le sottodirectory e i file e gestire efficacemente tali eccezioni.

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

Utilizzo di Tasks per file e directory di grandi dimensioni?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx è la versione Parallel Threading della soluzione precedente che utilizza una raccolta di stack e più veloce.
Markus

0

Uso il codice seguente con un form che ha 2 pulsanti, uno per l'uscita e l'altro per l'avvio. Una finestra di dialogo del browser delle cartelle e una finestra di salvataggio del file. Il codice è elencato di seguito e funziona sul mio sistema 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

Con questo puoi semplicemente eseguirli e scegliere la sottocartella quando viene eseguita la console

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

e questo è il patchar per l'esportazione 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);

La tua risposta non aggiunge nulla di nuovo a una risposta già esistente con il voto più alto.
locale predefinito

1
È anche sbagliato, poiché questo non restituisce alcuna directory (come specificato dalla domanda), solo file effettivi.
Alastair Maw

-1

Un po 'semplice e lento ma funzionante !! se non dai un percorso file usa "fixPath" questo è solo un esempio .... puoi cercare il fileType corretto quello che vuoi, ho fatto un errore quando ho scelto il nome dell'elenco perché "temporaryFileList è l'elenco dei file cercato quindi continua così .... e "errorList" parla da solo

 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

Crea elenco di stringhe

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

}

Questo non ottiene le sottodirectory.
TidyDev

-1

dir / s / b .> results.txt

/ s = sottocartelle / b = porta risultati

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.