列出目录及其子目录中的所有文件和文件夹

166

我想要列出指定目录及其子目录中包含的每个文件和目录的名称。如果我选择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
看看这个问题,然后去掉他匹配模式的部分。 - Sergey Kalinichenko
1
可能是一个重复的问题:如何在C#中递归列出目录中的所有文件? - JoshRivers
18个回答

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

你的回答并没有为已经存在的得票最高的回答增添任何新内容。 - default locale
1
这也是错误的,因为它不会返回任何目录(正如问题所指定的那样),只会返回实际的文件。 - Alastair Maw

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
当然,已经完成了,但它应该是自解释的。这是一个简单的循环递归遍历所有目录和文件。 - Sascha

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

使用任务(Tasks)处理大型文件和目录? - PreguntonCojoneroCabrón
https://msdn.microsoft.com/zh-cn/library/ff477033(v=vs.110).aspx 是使用堆栈集合的并行线程版本,速度更快的上述解决方案。 - Markus

0
请尝试以下代码以读取所有目录和子目录中的文件:
class Program
{
    static string _rootPath = @"D:\My Project\App_Data";
   
    static void Main(string[] args)
    {
        ReadDirectories(_rootPath);

        Console.ReadKey();
    }

    public static void ReadDirectories(string path, string directoryName = "")
    {
        if (!string.IsNullOrEmpty(directoryName))
        {
            Console.WriteLine("DIRECTORY NAME - {0}", directoryName);
            path = @$"{path}\{directoryName}";
        }

        DirectoryInfo dir_place = new DirectoryInfo(path);

        FileInfo[] Files = dir_place.GetFiles();
        foreach (FileInfo i in Files)
        {
            Console.WriteLine("{0} - FILE NAME - {1}", directoryName, i.Name);
        }

        DirectoryInfo[] directories = dir_place.GetDirectories();
        foreach (var directory in directories)
        {
            ReadDirectories(path, directory.Name);
        };
    }
}

“ReadDirectories”方法被调用,直到扫描完最后一个目录。


0

如果您无法访问目录树中的子文件夹,则Directory.GetFiles会停止并抛出异常,导致接收字符串数组中的空值。

在这里,看看这个答案https://dev59.com/bXVC5IYBdhLWcg3w1Exq#38959208

它在循环内部处理异常并继续工作,直到整个文件夹被遍历完毕。


-1

使用此功能,您可以直接运行它们并在控制台运行时选择子文件夹

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

这是用于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;
        }
    }
}

-2
创建字符串列表
    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);
            }

}

1
这不会获取子目录。 - TidyDev

-3

有点简单和慢,但是有效! 如果您没有提供文件路径,基本上使用“fixPath”这只是一个例子....您可以搜索您想要的正确文件类型,我在选择列表名称时犯了一个错误,因为“temporaryFileList”是搜索的文件列表,所以继续进行....而“errorList”则不言自明

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接