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

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个回答

280
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
2
GetFiles 方法返回一个字符串数组。 - Guffa
1
其实...你是对的... 我大约两天前开始学习Qt,有点误解了。 - Ruslan F.
这可能有效,但通常会因为UnauthorizedAccessException而失败。如何仅搜索它可以访问的目录? - derp_in_mouth
列出所有子目录(不包括文件),基于文件类型 string[] allDir = System.IO.Directory.GetDirectories(@"D:\\Images\", "*.jpg", SearchOption.AllDirectories); - sairfan
显示剩余2条评论

81

Directory.GetFileSystemEntries 函数存在于 .NET 4.0+ 中,返回文件和目录。您可以像下面这样调用它:

string[] entries = Directory.GetFileSystemEntries(path, "*", SearchOption.AllDirectories);
请注意,它无法处理尝试列出您无权访问的子目录的尝试(UnauthorizedAccessException),但对于您的需要可能已经足够。

4
这绝对是这里最好的答案。它只需一行代码即可获取所有文件和文件夹,而其他答案均无法做到。 - Steve Smith
我得到了一些隐藏文件夹,例如:“F:$RECYCLE.BIN”,“F:\System Volume Information”。如何忽略这些文件夹(仅获取在视图中显示的文件和文件夹)? - Yen Dang
1
@YenDang 在路径上调用 File.GetAttributes - MSDN 的示例代码专门演示了隐藏文件。 - Caius Jard

25
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
如果您能添加一些代码的解释,那么您的答案将会更好。 - Alex
它通过目录进行递归,并打印文件名或目录名。对于每个内部目录,它调用相同的函数。更多信息请参见:https://dev59.com/PHNA5IYBdhLWcg3wgeSk - I.Step

18

使用Substring函数来截取名称的左侧部分。 :) - Lucero
@Lucero 你为什么要这样做?Path提供了更可靠的方法。 - Gusdor
@Gusdor 如果您有更合适的建议,可以使用“Path”来删除路径中固定的左侧部分,例如在给定的示例中使用“C:\”。 - Lucero
@Lucero,我的评论表达得不太好。 “使用子字符串”并没有告诉我很多信息,所以我必须深入LinqPad中来推导出一个好的解决方案。例如,参数是什么?你会做path.SubString(2) 来天真地删除驱动器号和冒号吗?如果目录是网络共享呢?我建议使用Path作为可靠的方法,因为它可以在这个领域提供大量的好处。在这种情况下,您可以编写filePath.Substring(Path.GetPathRoot(filePath).Length)。是的,这使用了Substring,因为它是最简洁的。 - Gusdor

4

很抱歉,GetFiles 方法返回的是文件列表而不是目录。问题中的列表提示我结果应该包括文件夹。如果您想要更自定义的列表,可以尝试递归调用 GetFilesGetDirectories。请尝试以下代码:

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类。

2
一个晚回答,但我认为有人可能会从中受益。一个基于栈的迭代版本的起始程序,支持错误处理并返回相对路径:
private static IEnumerable<string> TryEnumerate(Func<IEnumerable<string>> action)
{
    try
    {
        return action.Invoke();
    }
    catch
    {
       //TODO logging
       return Enumerable.Empty<string>();
    }
}

private static IEnumerable<string> FindFilesAndDirectories(string dir, bool returnRelativePaths = false, string filePattern="*.*")
{
    var searchStack = new Stack<string>();
    searchStack.Push(dir);
    var initialDirectory = new DirectoryInfo(dir).FullName;
    var initialDirLength = initialDirectory.Length;

    while (searchStack.Count > 0)
    {
        var currentDirectory = searchStack.Pop();
            
        yield return (returnRelativePaths && 
                string.Compare(currentDirectory, initialDirectory, StringComparison.OrdinalIgnoreCase) != 0) ? 
                 currentDirectory.Substring(initialDirLength) : currentDirectory;

        foreach (var file in TryEnumerate(() =>
                 Directory.EnumerateFiles(currentDirectory, filePattern)))
        {
            yield return returnRelativePaths ? file.Substring(initialDirLength) : file;
        }

        foreach (var directory in TryEnumerate(() =>
                 Directory.EnumerateDirectories(currentDirectory, filePattern)))
        {
            searchStack.Push(directory);
        }
    }
}

static void Main(string[] args)
{
    foreach (var result in FindFilesAndDirectories(@"c:\", true))
    {
        Console.WriteLine(result);
    }
}

2
您可以使用FindFirstFile函数返回一个句柄,然后递归调用一个函数,该函数调用FindNextFile函数。这是一种不错的方法,因为引用的结构将填充各种数据,例如alternativeName、lastTmeCreated、modified、attributes等。
但是,由于您使用的是.net框架,因此您需要进入非托管区域。

2

有一些改进版本,最高级别可以在目录中向下移动,并且可以选择排除文件夹:

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的内容被排除在外;由于位于excludedFolders数组中,文件夹3的内容也被排除在外):

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

1
 public static List<string> GetAllFilesInDirectory(string targetDirectory, List<string> list = null)
        {
            if (list == null)
            {
                list = new List<string>();
            }

            string[] fileEntries = Directory.GetFiles(targetDirectory);

            foreach (string fileName in fileEntries)
            {
                list.Add(fileName);
            }

            string[] subdirectoryEntries = Directory.GetDirectories(targetDirectory);

            foreach (string subdirectory in subdirectoryEntries)
                GetAllFilesInDirectory(subdirectory, list);

            return list;
        }


1

我使用以下代码与一个有两个按钮的表单一起使用,一个用于退出,另一个用于启动。一个文件夹浏览对话框和一个保存文件对话框。下面列出了代码,并在我的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);
            }
        }
    }
}

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