Список усіх файлів і каталогів у каталозі + підкаталогах


109

Я хочу перерахувати кожен файл і каталог, що містяться в каталозі та підкаталогах цього каталогу. Якби я вибрав C: \ в якості каталогу, програма отримала б кожну назву кожного файлу та папки на жорсткому диску, до якого вона мала доступ.

Список може виглядати так

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

Перегляньте простір імен System.IO для класів та методів, які можуть вам допомогти.
Lucero

Ознайомтеся з цим запитанням і опустіть частину, де він відповідає шаблону.
dasblinkenlight

Відповіді:


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

де *.* шаблон для відповідності файлам

Якщо також потрібен Каталог, ви можете перейти так:

 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
Не справді буде робота ... Lsit<>клас? Що повертає GetFiles? А як щодо імен каталогів, які також запитували?
Lucero

1
GetFilesМетод повертає масив рядків.
Гуффа

фактично ... ви маєте рацію ... я вчу Qt abaout 2 дні тому і трохи помилявся
Ruslan F.

Це може спрацювати, але це часто не вдається з використанням несанкціонованого доступу. Як би шукати лише каталоги, до яких він має доступ?
derp_in_mouth

це означає, що у вашій системі для цього додатка недостатньо дозволів
Руслан Ф.

50

Directory.GetFileSystemEntriesіснує в .NET 4.0+ і повертає і файли, і каталоги. Назвіть це так:

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

Зауважте, що він не справляється зі спробами перерахування вмісту підкаталогів, до яких у вас немає доступу (UnauthorizedAccessException), але це може бути достатньо для ваших потреб.


3
Це, безумовно, найкраща відповідь тут. Він отримує всі файли та папки в одному рядку коду, чого ніхто з інших не робить.
Стів Сміт

15

Використовуйте GetDirectoriesі GetFilesметоди, щоб отримати папки та файли.

Використовуйте і для отримання папок і файлів у підпапках.SearchOption AllDirectories


Використовуйте підрядку, щоб відрізати ліву частину імені. :)
Lucero

@Lucero Як і чому ти це зробив? Pathпропонує більш надійні методи.
Гусдор

@Gusdor Не соромтеся запропонувати більш підходящий спосіб, використовуючи Pathдля видалення нерухомої лівої частини шляху, наприклад, "C:" у наведеному прикладі.
Лусеро

@Lucero мій коментар був погано сформульований. "Використовувати підрядку" не дуже мені розповідає, і мені довелося застрягти в linqpad, щоб отримати гарне рішення. Наприклад, яким буде параметр? Ви збираєтесь робити path.SubString(2)наївне видалення букви диска та двокрапки? Що робити, якщо каталог є мережевою часткою? Я пропоную Pathяк надійний метод, оскільки він може забезпечити безліч смаколиків у цій галузі. У цьому випадку ви можете написати filePath.Substring(Path.GetPathRoot(filePath).Length). Так, для цього використовується Підрядка, оскільки вона є найбільш стислою.
Гусдор

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
Ваша відповідь покращиться, якщо ви зможете додати трохи пояснень того, що робить код.
Олексій

Він проходить рекурсивно через каталог і друкує назви файлів або імена каталогів. Для кожного внутрішнього каталогу він називає ту саму функцію. Для отримання додаткової інформації: stackoverflow.com/questions/929276 / ...
I.Step

3

Боюся, GetFilesметод повертає список файлів, але не каталогів. Список у запитанні підказує, що результат повинен містити і папки. Якщо ви хочете отримати більше індивідуального списку, ви можете спробувати дзвонити GetFilesта GetDirectoriesрекурсивно. Спробуйте це:

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

Порада: Ви можете використовувати FileInfoта DirectoryInfoкласи, якщо вам потрібно перевірити будь-який конкретний атрибут.


1

Ви можете використовувати FindFirstFile, який повертає ручку, а потім рекурсивно викликає функцію, яка викликає FindNextFile. Це хороший підхід, оскільки посилання на структуру наповнюватиметься різними даними, такими як AlternativeName, lastTmeCreate, модифіковані, атрибути тощо

Але при використанні .net фреймворку вам доведеться увійти в некеровану область.


1

Деякі вдосконалені версії з максимальним lvl, щоб увійти в каталог та опцію для виключення папок:

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

вхідний каталог:

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

вихід функції (вміст папки5 виключається через обмеження lvl, а вміст папки3 виключається, оскільки він знаходиться у масиві виключених папок):

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

0

Якщо у вас немає доступу до підпапки всередині дерева каталогів, Directory.GetFiles зупиняється та видаляє виняток, в результаті чого в приймальному рядку виникає нульове значення [].

Ось дивіться цю відповідь https://stackoverflow.com/a/38959208/6310707

Він управляє винятком всередині циклу і продовжує працювати, поки не пройде вся папка.


0

логічний і впорядкований спосіб:

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

Чи можете ви надати пояснення чи внутрішні коментарі, що робить ваш код?
MarthyM

звичайно, зробили це, але це повинно бути зрозумілим, це проста циклічна рекурсія через усі каталоги та файли
Саша,

0

Наступний приклад найшвидший (не паралельний) спосіб перерахування файлів та підпапок у дереві каталогів, що обробляє винятки. Швидше було б скористатися Directory.EnumerateDirectories, використовуючи SearchOption.AllDirectories, щоб перерахувати всі каталоги, але цей спосіб не вдасться, якщо потрапить на UnauthorizedAccessException або PathTooLongException.

Використовується загальний тип колекції Stack, який є останнім у стеку (LIFO) та не використовує рекурсії. З https://msdn.microsoft.com/en-us/library/bb513869.aspx дозволяє перелічити всі підкаталоги та файли та ефективно попрацювати з цими винятками.

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

Використання завдань для великої кількості файлів і каталогів?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx - це версія паралельної нитки вищевказаного рішення з використанням колекції стека та швидше.
Маркус

0

Я використовую наступний код із формою, яка має 2 кнопки, одну для виходу, а другу для запуску. Діалогове вікно браузера папок та діалогове вікно збереження файлу. Код перелічено нижче і працює в моїй системі 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);
            }
        }
    }
}

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

Ваша відповідь не додає нічого нового до вже існуючої голосової відповіді.
локальне місце за замовчуванням

1
Це також неправильно, оскільки це не повертає жодних каталогів (як зазначено в питанні), а лише фактичні файли.
Аластер Мау

-1

Маленький біт простий і повільно, але працює !! якщо ви не даєте filepath в основному використовувати "fixPath", це лише приклад .... ви можете шукати правильний файл. Введіть те, що ви хочете, я помилився, коли вибрав назву списку, тому що "тимчасовий список файлів - це список шуканих файлів тож продовжуйте це .... і "список помилок" говорить сам за себе

 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

Створити список рядків

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

}

Це не отримує підкаталоги.
TidyDev

-1

dir / s / b .> результати.txt

/ s = підпапки / b = несуть результати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.