Wyświetla wszystkie pliki i katalogi w katalogu + podkatalogach

109

Chcę wyświetlić wszystkie pliki i katalogi zawarte w katalogu i podkatalogach tego katalogu. Gdybym wybrał C: \ jako katalog, program uzyskałby każdą nazwę każdego pliku i folderu na dysku twardym, do którego miał dostęp.

Może wyglądać lista

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
derp_in_mouth
źródło
Przejrzyj przestrzeń nazw System.IO w poszukiwaniu klas i metod, które mogą Ci pomóc.
Lucero,
Sprawdź to pytanie i upuść część, w której dopasowuje wzór.
dasblinkenlight

Odpowiedzi:

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

gdzie *.*jest wzorzec pasujący do plików

Jeśli katalog jest również potrzebny, możesz przejść w ten sposób:

 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();
 }
Rusłan F.
źródło
1
Naprawdę nie będzie pracować ... Lsit<>klasa? Co zwraca GetFiles? A co z nazwami katalogów, które również były wymagane?
Lucero,
1
GetFilesSposób powraca tablicę napisów.
Guffa,
faktycznie ... masz rację ... uczę się Qt około 2 dni temu i trochę się pomyliłem
Ruslan F.
Może to zadziałać, ale często kończy się niepowodzeniem z wyjątkiem UnauthorizedAccessException. Jak przeszukiwać tylko te katalogi, do których ma dostęp?
derp_in_mouth,
oznacza to, że w Twoim systemie ta aplikacja nie ma wystarczających uprawnień
Ruslan F.
50

Directory.GetFileSystemEntriesistnieje w .NET 4.0+ i zwraca zarówno pliki, jak i katalogi. Nazwij to tak:

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

Zauważ, że nie poradzi sobie z próbami wylistowania zawartości podkatalogów, do których nie masz dostępu (UnauthorizedAccessException), ale może być wystarczające dla twoich potrzeb.

Alastair Maw
źródło
3
To zdecydowanie najlepsza odpowiedź. Pobiera wszystkie pliki i foldery w jednej linii kodu, czego nie robi żaden z pozostałych.
Steve Smith
15

Użyj metod GetDirectoriesi GetFiles, aby pobrać foldery i pliki.

Użyj, aby pobrać foldery i pliki w podfolderach.SearchOption AllDirectories

Guffa
źródło
Użyj Podciąg, aby odciąć lewą część nazwy. :)
Lucero,
@Lucero Jak i dlaczego miałbyś to zrobić? Pathoferuje bardziej niezawodne metody.
Gusdor
@Gusdor Możesz zasugerować bardziej odpowiedni sposób, używając Pathdo usunięcia stałej lewej części ścieżki, np. `C:` w podanym przykładzie.
Lucero
@Lucero mój komentarz był źle sformułowany. „Użyj podciągu” niewiele mi mówi i musiałem utknąć w linqpadzie, aby uzyskać dobre rozwiązanie. Na przykład jaki byłby parametr? Czy zamierzasz path.SubString(2)naiwnie usunąć literę dysku i dwukropek? A jeśli katalog jest udziałem sieciowym? Proponuję Pathjako niezawodną metodę, ponieważ może zapewnić mnóstwo bajerów w tej dziedzinie. W takim przypadku możesz napisać filePath.Substring(Path.GetPathRoot(filePath).Length). Tak, to używa podłańcucha, ponieważ jest najbardziej zwięzła.
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);
    }
}
Evan Dangol
źródło
3
Poprawiłoby twoją odpowiedź, gdybyś mógł dodać trochę wyjaśnienia, co robi kod.
Alex
Przechodzi rekurencyjnie przez katalog i wyświetla nazwy plików lub katalogów. Dla każdego katalogu wewnętrznego wywołuje tę samą funkcję. Więcej informacji: stackoverflow.com/questions/929276/ ...
krok
3

Obawiam się, że GetFilesmetoda zwraca listę plików, ale nie katalogów. Lista w pytaniu podpowiada mi, że wynik powinien zawierać również foldery. Jeśli chcesz bardziej spersonalizowaną listę, możesz spróbować wywołać GetFilesi GetDirectoriesrekurencyjnie. Spróbuj tego:

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

Wskazówka: możesz użyć klas FileInfoi DirectoryInfo, jeśli chcesz sprawdzić określony atrybut.

Krishna Sarma
źródło
1

Możesz użyć FindFirstFile, który zwraca uchwyt, a następnie rekurencyjnie wywołuje funkcję, która wywołuje FindNextFile.Jest to dobre podejście, ponieważ struktura, do której się odwołuje, byłaby wypełniona różnymi danymi, takimi jak alternatywaName, lastTmeCreated, modified, atrybuty itp.

Ale kiedy używasz .net Framework, musisz wejść do niezarządzanego obszaru.

Reznicencu Bogdan
źródło
1

Ulepszona wersja z max lvl do zejścia w dół w katalogu i opcją wykluczenia folderów:

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

katalog wejściowy:

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

wyjście funkcji (zawartość folderu 5 jest wykluczona ze względu na limit lvl, a zawartość folderu 3 jest wykluczona, ponieważ znajduje się w tablicy excludedFolders):

-folder1
  file1.txt
  -folder2
    file2.txt
    -folder5
  -folder3
  -folder4
    file4.txt
    file5.txt
brainoverflow98
źródło
0

Jeśli nie masz dostępu do podfolderu w drzewie katalogów, Directory.GetFiles zatrzymuje się i zgłasza wyjątek powodujący wartość null w ciągu odbierającym [].

Tutaj zobacz tę odpowiedź https://stackoverflow.com/a/38959208/6310707

Zarządza wyjątkiem wewnątrz pętli i kontynuuje pracę, aż przejdzie cały folder.

Shubham
źródło
0

logiczny i uporządkowany sposób:

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);
            }
        }
    }
}
}
Sascha
źródło
Czy mógłbyś podać wyjaśnienie lub komentarze w linii, co robi twój kod?
MarthyM
oczywiście, zrobiłem to, ale powinno to być oczywiste, jest to prosta rekurencja w pętli przez wszystkie katalogi i pliki
Sascha
0

Poniższy przykład najszybszy (nie zrównoleglony) sposób wyświetla listę plików i podfolderów w drzewie katalogów obsługujących wyjątki. Szybsze byłoby użycie Directory.EnumerateDirectories przy użyciu SearchOption.AllDirectories do wyliczenia wszystkich katalogów, ale ta metoda zakończy się niepowodzeniem, jeśli trafi w wyjątek UnauthorizedAccessException lub PathTooLongException.

Używa ogólnego typu kolekcji Stack, który jest stosem last in first out (LIFO) i nie używa rekursji. Ze strony https://msdn.microsoft.com/en-us/library/bb513869.aspx umożliwia wyliczenie wszystkich podkatalogów i plików oraz efektywne radzenie sobie z tymi wyjątkami.

    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);
        }
    }
}
Markus
źródło
Używasz zadań do obsługi dużej liczby plików i katalogów?
PreguntonCojoneroCabrón
msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx to wersja z równoległym wątkiem powyższego rozwiązania korzystająca ze zbioru stosu i szybsza.
Markus
0

Używam następującego kodu z formularzem, który ma 2 przyciski, jeden do wyjścia, a drugi do uruchomienia. Okno dialogowe przeglądarki folderów i okno dialogowe zapisywania pliku. Kod znajduje się poniżej i działa w moim systemie 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);
            }
        }
    }
}
Garry
źródło
0

Dzięki temu możesz je po prostu uruchomić i wybrać podfolder po uruchomieniu konsoli

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

i to jest patchar do eksportu 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;
        }
    }
}
Smar ts
źródło
-1
using System.IO;
using System.Text;
string[] filePaths = Directory.GetFiles(@"path", "*.*", SearchOption.AllDirectories);
aah
źródło
Twoja odpowiedź nie dodaje niczego nowego do już istniejącej odpowiedzi z największą liczbą głosów.
domyślny język
1
Jest to również błędne, ponieważ nie zwraca to żadnych katalogów (jak określono w pytaniu), tylko rzeczywiste pliki.
Alastair Maw
-1

Trochę proste i powoli, ale działa !! jeśli nie podasz ścieżki do pliku, użyj "fixPath" to tylko przykład .... możesz wyszukaćpoprawny fileType co chcesz, popełniłem błąd kiedy wybrałem nazwę listy ponieważ "tymczasowa lista_plików jest przeszukiwaną listą plików więc kontynuuj ... a „errorList” mówi samo za siebie

 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);
    }
Peka
źródło
-1

Utwórz listę ciągów

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

}
رضا جون
źródło
To nie powoduje pobrania podkatalogów.
TidyDev
-1

dir / s / b . > wyniki.txt

/ s = podfoldery / b = wyniki niedźwiedzia

bd_iii
źródło