Liệt kê tất cả các tệp và thư mục trong một thư mục + thư mục con


109

Tôi muốn liệt kê mọi tệp và thư mục có trong một thư mục và các thư mục con của thư mục đó. Nếu tôi chọn C: \ làm thư mục, chương trình sẽ lấy mọi tên của mọi tệp và thư mục trên ổ cứng mà nó có quyền truy cập.

Một danh sách có thể trông giống như

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

Duyệt qua không gian tên System.IO để tìm các lớpphương thức có thể giúp bạn.
Lucero

Hãy xem câu hỏi này và bỏ qua phần mà anh ấy khớp với một mẫu.
dasblinkenlight

Câu trả lời:


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

đâu *.*là mẫu để khớp các tệp

Nếu cũng cần Thư mục, bạn có thể đi như sau:

 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
Sẽ không thực sự hoạt động ... Lsit<>lớp học? GetFiles trả về những gì? Và những gì về các tên thư mục cũng được yêu cầu?
Lucero

1
Các GetFilesphương thức trả về một mảng chuỗi.
Guffa

actualy ... bạn là đúng ... Tôi đang học Qt abaout 2 ngày trước và có một chút nhầm lẫn
Ruslan F.

Điều này có thể hoạt động, nhưng nó thường không thành công với UnauthorizedAccessException. Làm thế nào để chỉ tìm kiếm các thư mục mà nó có thể truy cập?
derp_in_mouth

điều đó có nghĩa là trong hệ thống của bạn, ứng dụng này không có đủ quyền
Ruslan F.

50

Directory.GetFileSystemEntriestồn tại trong .NET 4.0+ và trả về cả tệp và thư mục. Gọi nó như vậy:

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

Lưu ý rằng nó sẽ không đối phó với những nỗ lực liệt kê nội dung của các thư mục con mà bạn không có quyền truy cập (UnauthorizedAccessException), nhưng nó có thể đủ cho nhu cầu của bạn.


3
Đây là câu trả lời tốt nhất ở đây. Nó nhận tất cả các tệp và thư mục trong một dòng mã, điều mà không dòng nào khác làm được.
Steve Smith

15

Sử dụng GetDirectoriesGetFilescác phương pháp để lấy các thư mục và tệp.

Cũng sử dụng để lấy các thư mục và tệp trong các thư mục con.SearchOption AllDirectories


Sử dụng Substring để cắt bỏ phần bên trái của tên. :)
Lucero

@Lucero Làm thế nào và tại sao bạn sẽ làm điều đó? Pathcung cấp các phương pháp đáng tin cậy hơn.
Gusdor

@Gusdor Vui lòng đề xuất một cách phù hợp hơn bằng cách sử dụng Pathđể loại bỏ phần bên trái cố định của đường dẫn, ví dụ: `C: 'trong ví dụ đã cho.
Lucero

@Lucero bình luận của tôi diễn đạt kém. 'Sử dụng chuỗi con' không cho tôi biết nhiều điều và tôi đã phải mắc kẹt vào linqpad để tìm ra một giải pháp tốt. Ví dụ, tham số sẽ là gì? Bạn sẽ làm gì path.SubString(2)để loại bỏ ký tự ổ đĩa và dấu hai chấm một cách ngây thơ? Nếu thư mục là mạng chia sẻ thì sao? Tôi đề xuất Pathnhư một phương pháp đáng tin cậy vì nó có thể cung cấp vô số tính năng trong lĩnh vực này. Trong trường hợp này, bạn có thể viết filePath.Substring(Path.GetPathRoot(filePath).Length). Có, điều này sử dụng Chuỗi con vì nó ngắn gọn nhất.
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
Nó sẽ cải thiện câu trả lời của bạn nếu bạn có thể thêm một chút giải thích về chức năng của mã.
Alex

Nó đi đệ quy qua thư mục và in tên tệp hoặc tên thư mục. Đối với mọi thư mục bên trong, nó gọi cùng một hàm. Để biết thêm thông tin: stackoverflow.com/questions/929276/…
I.Bước

3

Tôi sợ, GetFilesphương thức trả về danh sách các tệp nhưng không phải là thư mục. Danh sách trong câu hỏi nhắc tôi rằng kết quả cũng nên bao gồm các thư mục. Nếu bạn muốn danh sách tùy chỉnh nhiều hơn, bạn có thể thử gọi GetFilesGetDirectoriesđệ quy. Thử cái này:

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

Mẹo: Bạn có thể sử dụng FileInfoDirectoryInfocác lớp nếu bạn cần kiểm tra bất kỳ thuộc tính cụ thể nào.


1

Bạn có thể sử dụng FindFirstFile trả về một xử lý và sau đó gọi một cách đệ quy một hàm gọi FindNextFile.

Nhưng khi bạn sử dụng khung .net, bạn sẽ phải vào vùng không được quản lý.


1

Một số phiên bản cải tiến với lvl tối đa để đi xuống thư mục và tùy chọn để loại trừ các thư mục:

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

thư mục đầu vào:

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

đầu ra của hàm (nội dung của thư mục5 bị loại trừ do giới hạn lvl và nội dung của thư mục3 bị loại trừ vì nó nằm trong mảng Thư mục bị loại trừ):

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

0

Nếu bạn không có quyền truy cập vào thư mục con bên trong cây thư mục, Directory.GetFiles sẽ dừng và ném ngoại lệ dẫn đến giá trị null trong chuỗi nhận [].

Tại đây, hãy xem câu trả lời này https://stackoverflow.com/a/38959208/6310707

Nó quản lý ngoại lệ bên trong vòng lặp và tiếp tục hoạt động cho đến khi toàn bộ thư mục được duyệt.


0

cách hợp lý và có thứ tự:

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

Bạn có thể vui lòng cung cấp lời giải thích hoặc nhận xét nội dòng, mã của bạn làm gì?
MarthyM

tất nhiên, làm được điều đó, nhưng nó phải là tự giải thích, đó là một đơn giản lặp đệ quy qua tất cả các thư mục và các tập tin
Sascha

0

Ví dụ sau đây là nhanh nhất (không song song) liệt kê các tệp và thư mục con trong cây thư mục xử lý các ngoại lệ. Sẽ nhanh hơn nếu sử dụng Directory.EnumerateDirectories bằng cách sử dụng SearchOption.AllDirectories để liệt kê tất cả các thư mục, nhưng phương pháp này sẽ thất bại nếu truy cập vào UnauthorizedAccessException hoặc PathTooLongException.

Sử dụng kiểu tập hợp Ngăn xếp chung, là ngăn xếp cuối cùng vào trước (LIFO) và không sử dụng đệ quy. Từ https://msdn.microsoft.com/en-us/library/bb513869.aspx , cho phép bạn liệt kê tất cả các thư mục con và tệp và xử lý hiệu quả với những ngoại lệ đó.

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

Sử dụng Task cho các tệp và thư mục có số lượng lớn?
PreguntonCojoneroCabrón

msdn.microsoft.com/en-us/library/ff477033(v=vs.110).aspx là phiên bản Luồng song song của giải pháp trên sử dụng bộ sưu tập ngăn xếp và nhanh hơn.
Markus

0

Tôi sử dụng mã sau với một biểu mẫu có 2 nút, một để thoát và nút kia để bắt đầu. Hộp thoại trình duyệt thư mục và hộp thoại lưu tệp. Mã được liệt kê bên dưới và hoạt động trên hệ thống của tôi 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

Với điều này, bạn chỉ có thể chạy chúng và chọn thư mục con khi bảng điều khiển chạy

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

và đây là phụ phí cho việc xuất 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);

Câu trả lời của bạn không thêm bất cứ điều gì mới vào câu trả lời được bình chọn nhiều nhất hiện có.
ngôn ngữ mặc định

1
Nó cũng sai, vì điều này không trả về bất kỳ thư mục nào (như câu hỏi đã chỉ định), chỉ các tệp thực tế.
Alastair Maw

-1

Một chút đơn giản và chậm rãi nhưng hiệu quả !! nếu bạn không cung cấp đường dẫn tệp về cơ bản hãy sử dụng "fixPath", đây chỉ là ví dụ .... bạn có thể tìm kiếm đúng fileType những gì bạn muốn, tôi đã nhầm lẫn khi chọn tên danh sách vì "tạm thờiFileList là danh sách tệp được tìm kiếm vì vậy hãy tiếp tục điều đó .... và "errorList" tự nói lên

 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

Tạo danh sách chuỗi

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

}

Điều này không nhận được các thư mục con.
TidyDev

-1

dir / s / b .> results.txt

/ s = subfolders / b = bear results

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.