Как рекурсивно перечислить все файлы в каталоге и дочерних каталогах на С#?
Как рекурсивно перечислить все файлы в каталоге на С#?
Ответ 1
Эта статья охватывает все, что вам нужно. За исключением случаев поиска в файлах и сравнения имен, просто распечатайте имена.
Его можно изменить так:
static void DirSearch(string sDir)
{
    try
    {
        foreach (string d in Directory.GetDirectories(sDir))
        {
            foreach (string f in Directory.GetFiles(d))
            {
                Console.WriteLine(f);
            }
            DirSearch(d);
        }
    }
    catch (System.Exception excpt)
    {
        Console.WriteLine(excpt.Message);
    }
}
Ответ 2
Обратите внимание, что в .NET 4.0 встроены (предположительно) основанные на итераторах (а не на массивах) файловые функции:
foreach (string file in Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories))
{
    Console.WriteLine(file);
}
На данный момент я бы использовал что-то вроде ниже; встроенный рекурсивный метод ломается слишком легко, если у вас нет доступа к одному подкаталогу...; использование Queue<string> позволяет избежать слишком большой рекурсии стека вызовов, а блок итератора позволяет избежать огромного массива.
static void Main() {
    foreach (string file in GetFiles(SOME_PATH)) {
        Console.WriteLine(file);
    }
}
static IEnumerable<string> GetFiles(string path) {
    Queue<string> queue = new Queue<string>();
    queue.Enqueue(path);
    while (queue.Count > 0) {
        path = queue.Dequeue();
        try {
            foreach (string subDir in Directory.GetDirectories(path)) {
                queue.Enqueue(subDir);
            }
        }
        catch(Exception ex) {
            Console.Error.WriteLine(ex);
        }
        string[] files = null;
        try {
            files = Directory.GetFiles(path);
        }
        catch (Exception ex) {
            Console.Error.WriteLine(ex);
        }
        if (files != null) {
            for(int i = 0 ; i < files.Length ; i++) {
                yield return files[i];
            }
        }
    }
}
Ответ 3
Directory.GetFiles("C:\\", "*.*", SearchOption.AllDirectories)
Ответ 4
В .NET 4.5, по крайней мере, есть эта версия, которая намного короче и имеет дополнительный бонус для оценки любых критериев файла для включения в список:
    /// </remarks>
    public static IEnumerable<string> GetAllFiles(string path, Func<FileInfo, bool> checkFile = null)
    {
        string mask = Path.GetFileName(path);
        if (string.IsNullOrEmpty(mask))
            mask = "*.*";
        path = Path.GetDirectoryName(path);
        string[] files = Directory.GetFiles(path, mask, SearchOption.AllDirectories);
        foreach (string file in files)
        {
            if (checkFile == null || checkFile(new FileInfo(file)))
                yield return file;
        }
    }
Используйте как:
        string folder = Config.TestInput();
        string mask = folder + "*.*";
        var list = UT.GetAllFiles(mask, (info) => Path.GetExtension(info.Name) == ".html").ToList();
        Assert.AreNotEqual(0, list.Count);
        var lastQuarter = DateTime.Now.AddMonths(-3);
        list = UT.GetAllFiles(mask, (info) => info.CreationTime >= lastQuarter).ToList();
        Assert.AreNotEqual(0, list.Count);
Ответ 5
IEnumerable<string> GetFilesFromDir(string dir) =>
 Directory.EnumerateFiles(dir).Concat(
 Directory.EnumerateDirectories(dir)
          .SelectMany(subdir => GetFilesFromDir(subdir)));
Ответ 6
Некоторые отличные ответы, но эти ответы не помогли решить мою проблему.
Как только возникает проблема с правами на доступ к папке: "Permission Denied" сбой кода. Это то, что я использовал, чтобы обойти проблему "Разрешение отказа":
private int counter = 0;
    private string[] MyDirectories = Directory.GetDirectories("C:\\");
    private void ScanButton_Click(object sender, EventArgs e)
    {
        Thread MonitorSpeech = new Thread(() => ScanFiles());
        MonitorSpeech.Start();
    }
    private void ScanFiles()
    {
        string CurrentDirectory = string.Empty;
        while (counter < MyDirectories.Length)
        {
            try
            {
                GetDirectories();
                CurrentDirectory = MyDirectories[counter++];
            }
            catch
            {
                if (!this.IsDisposed)
                {
                    listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + CurrentDirectory); });
                }
            }
        }
    }
    private void GetDirectories()
    {
        foreach (string directory in MyDirectories)
        {
            GetFiles(directory);
        }
    }
    private void GetFiles(string directory)
    {
        try
        {
            foreach (string file in Directory.GetFiles(directory, "*"))
            {
                listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add(file); });
            }
        }
        catch
        {
            listBox1.Invoke((MethodInvoker)delegate { listBox1.Items.Add("Access Denied to : " + directory); });
        }
    }
Надеюсь, что это поможет другим.
Ответ 7
В Framework 2.0 вы можете использовать (Он перечисляет файлы корневой папки, это самый лучший ответ):
static void DirSearch(string dir)
{
    try
    {
        foreach (string f in Directory.GetFiles(dir))
            Console.WriteLine(f);
        foreach (string d in Directory.GetDirectories(dir))
        {
            Console.WriteLine(d);
            DirSearch(d);
        }
    }
    catch (System.Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Ответ 8
Простое и чистое решение
/// <summary>
/// Scans a folder and all of its subfolders recursively, and updates the List of files
/// </summary>
/// <param name="sFullPath">Full path of the folder</param>
/// <param name="files">The list, where the output is expected</param>
internal static void EnumerateFiles(string sFullPath, List<FileInfo> fileInfoList)
{
    try
    {
        DirectoryInfo di = new DirectoryInfo(sFullPath);
        FileInfo[] files = di.GetFiles();
        foreach (FileInfo file in files)
            fileInfoList.Add(file);
        //Scan recursively
        DirectoryInfo[] dirs = di.GetDirectories();
        if (dirs == null || dirs.Length < 1)
            return;
        foreach (DirectoryInfo dir in dirs)
            EnumerateFiles(dir.FullName, fileInfoList);
    }
    catch (Exception ex)
    {
        Logger.Write("Exception in Helper.EnumerateFiles", ex);
    }
}
Ответ 9
Я предпочитаю использовать DirectoryInfo, потому что я могу получить FileInfo, а не только строки.
        string baseFolder = @"C:\temp";
        DirectoryInfo di = new DirectoryInfo(baseFolder);
        string searchPattern = "*.xml";
        ICollection<FileInfo> matchingFileInfos = di.GetFiles(searchPattern, SearchOption.AllDirectories)
            .Select(x => x)
            .ToList();
Я делаю это в случае, если в будущем мне понадобится будущая фильтрация.. основываясь на свойствах FileInfo.
        string baseFolder = @"C:\temp";
        DirectoryInfo di = new DirectoryInfo(baseFolder);
        string searchPattern = "*.xml";
        ICollection<FileInfo> matchingFileInfos = di.GetFiles(searchPattern, SearchOption.AllDirectories)
            .Where(x => x.LastWriteTimeUtc < DateTimeOffset.Now)
            .Select(x => x)
            .ToList();
При необходимости я могу вернуться к строкам. (и до сих пор я буду в дальнейшем проверяться на наличие фильтров /where -clause.
        string baseFolder = @"C:\temp";
        DirectoryInfo di = new DirectoryInfo(baseFolder);
        string searchPattern = "*.xml";
        ICollection<string> matchingFileNames = di.GetFiles(searchPattern, SearchOption.AllDirectories)
            .Select(x => x.FullName)
            .ToList();
Обратите внимание, что "." является допустимым шаблоном поиска, если вы хотите, чтобы файл был добавлен расширением.
Ответ 10
 Чтобы избежать UnauthorizedAccessException, я использую:
var files = GetFiles(@"C:\", "*.*", SearchOption.AllDirectories);
foreach (var file in files)
{
    Console.WriteLine($"{file}");
}
public static IEnumerable<string> GetFiles(string path, string searchPattern, SearchOption searchOption)
{
    var foldersToProcess = new List<string>()
    {
        path
    };
    while (foldersToProcess.Count > 0)
    {
        string folder = foldersToProcess[0];
        foldersToProcess.RemoveAt(0);
        if (searchOption.HasFlag(SearchOption.AllDirectories))
        {
            //get subfolders
            try
            {
                var subfolders = Directory.GetDirectories(folder);
                foldersToProcess.AddRange(subfolders);
            }
            catch (Exception ex)
            {
                //log if you're interested
            }
        }
        //get files
        var files = new List<string>();
        try
        {
            files = Directory.GetFiles(folder, searchPattern, SearchOption.TopDirectoryOnly).ToList();
        }
        catch (Exception ex)
        {
            //log if you're interested
        }
        foreach (var file in files)
        {
            yield return file;
        }
    }
}
Ответ 11
Здесь мой угол на нем, основанный на Hernaldo's, если вам нужно найти файлы с именами определенного шаблона, например файлы XML, которые где-то в их имени содержат определенную строку:
// call this like so: GetXMLFiles("Platypus", "C:\\");
public static List<string> GetXMLFiles(string fileType, string dir)
{
    string dirName = dir; 
    var fileNames = new List<String>();
    try
    {
        foreach (string f in Directory.GetFiles(dirName))
        {
            if ((f.Contains(fileType)) && (f.Contains(".XML")))
            {
                fileNames.Add(f);
            }
        }
        foreach (string d in Directory.GetDirectories(dirName))
        {
            GetXMLFiles(fileType, d);
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
    return fileNames;
}
Ответ 12
Список файлов и папок для модели, пользовательская реализация. 
Это создает полный список всех файлов и папок, начиная с вашего стартового каталога.
public class DirOrFileModel
    {
        #region Private Members
        private string _name;
        private string _location;
        private EntryType _entryType;
        #endregion
        #region Bindings
        public string Name
        {
            get { return _name; }
            set
            {
                if (value == _name) return;
                _name = value;
            }
        }
        public string Location
        {
            get { return _location; }
            set
            {
                if (value == _location) return;
                _location = value;
            }
        }
        public EntryType EntryType
        {
            get { return _entryType; }
            set
            {
                if (value == _entryType) return;
                _entryType = value;
            }
        }
        public ObservableCollection<DirOrFileModel> Entries { get; set; }
        #endregion
        #region Constructor
        public DirOrFileModel()
        {
            Entries = new ObservableCollection<DirOrFileModel>();
        }
        #endregion
    }
    public enum EntryType
    {
        Directory = 0,
        File = 1
    }
Метод:
 static DirOrFileModel DirSearch(DirOrFileModel startDir)
        {
            var currentDir = startDir;
            try
            {
                foreach (string d in Directory.GetDirectories(currentDir.Location))
                {
                    var newDir = new DirOrFileModel
                    {
                        EntryType = EntryType.Directory,
                        Location = d,
                        Name = Path.GetFileName(d)
                    };
                    currentDir.Entries.Add(newDir);
                    DirSearch(newDir);
                }
                foreach (string f in Directory.GetFiles(currentDir.Location))
                {
                    var newFile = new DirOrFileModel
                    {
                        EntryType = EntryType.File,
                        Location = f,
                        Name = Path.GetFileNameWithoutExtension(f)
                    };
                    currentDir.Entries.Add(newFile);
                }
            }
            catch (Exception excpt)
            {
                Console.WriteLine(excpt.Message);
            }
            return startDir;
        }
Использование:
var dir = new DirOrFileModel
            {
                Name = "C",
                Location = @"C:\",
                EntryType = EntryType.Directory
            };
            dir = DirSearch(dir);
Ответ 13
private void GetFiles(DirectoryInfo dir, ref List<FileInfo> files)
{
    try
    {
        files.AddRange(dir.GetFiles());
        DirectoryInfo[] dirs = dir.GetDirectories();
        foreach (var d in dirs)
        {
            GetFiles(d, ref files);
        }
    }
    catch (Exception e)
    {
    }
}
Ответ 14
Краткое и простое решение
string dir = @"D:\PATH";
DateTime from_date = DateTime.Now.Date;
DateTime to_date = DateTime.Now.Date.AddHours(23);
var files = Directory.EnumerateFiles(dir, "*.*",SearchOption.AllDirectories).Select(i=>new FileInfo(i))
.Where(file=>file.LastWriteTime >= from_date && file.LastWriteTime <= to_date);
foreach(var fl in files)
    Console.WriteLine(fl.FullName);
Ответ 15
Этот помог мне собрать все файлы в каталог и подкаталоги, может быть, кому-то пригодится. [Вдохновленные сверху ответы]
static void Main(string[] args)
    {
        try
        {
            var root = @"G:\logs";
            DirectorySearch(root);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
        Console.ReadKey();
    }
public static void DirectorySearch(string root, bool isRootItrated = false)
{
    if (!isRootItrated)
    {
        var rootDirectoryFiles = Directory.GetFiles(root);
        foreach (var file in rootDirectoryFiles)
        {
            Console.WriteLine(file);
        } 
    }
    var subDirectories = Directory.GetDirectories(root);
    if (subDirectories?.Any() == true)
    {
        foreach (var directory in subDirectories)
        {
            var files = Directory.GetFiles(directory);
            foreach (var file in files)
            {
                Console.WriteLine(file);
            }
            DirectorySearch(directory, true);
        }
    }
}
Ответ 16
var d = new DirectoryInfo(@"C:\logs");
var list = d.GetFiles("*.txt").Select(m => m.Name).ToList();
Ответ 17
Вот версия кода B. Clay Shannon, не статическая для excel файлов:
class ExcelSearcher
{
    private List<string> _fileNames;
    public ExcelSearcher(List<string> filenames)
    {
        _fileNames = filenames;
    }
    public List<string> GetExcelFiles(string dir, List<string> filenames = null)
    {
        string dirName = dir;
        var dirNames = new List<string>();
        if (filenames != null)
        {
            _fileNames.Concat(filenames);
        }
        try
        {
            foreach (string f in Directory.GetFiles(dirName))
            {
                if (f.ToLower().EndsWith(".xls") || f.ToLower().EndsWith(".xlsx"))
                {
                    _fileNames.Add(f);
                }
            }
            dirNames = Directory.GetDirectories(dirName).ToList();
            foreach (string d in dirNames)
            {
                GetExcelFiles(d, _fileNames);
            }
        }
        catch (Exception ex)
        {
            //Bam
        }
        return _fileNames;
    }
Ответ 18
static void Main(string[] args)
        {
            string[] array1 = Directory.GetFiles(@"D:\");
            string[] array2 = System.IO.Directory.GetDirectories(@"D:\");
            Console.WriteLine("--- Files: ---");
            foreach (string name in array1)
            {
                Console.WriteLine(name);
            }
            foreach (string name in array2)
            {
                Console.WriteLine(name);
            }
                  Console.ReadLine();
        }
Ответ 19
Очень простое решение, возвращает список файлов.
    public static List<string> AllFilesInFolder(string folder)
    {
        var result = new List<string>();
        foreach (string f in Directory.GetFiles(folder))
        {
            result.Add(f);
        }
        foreach (string d in Directory.GetDirectories(folder))
        {
            result.AddRange(AllFilesInFolder(d));
        }
        return result;
    }
