List all files and directories in a directory + subdirectories

C#DirectorySubdirectoryGetdirectories

C# Problem Overview


I want to list every file and directory contained in a directory and subdirectories of that directory. If I chose C:\ as the directory, the program would get every name of every file and folder on the hard drive that it had access to.

A list might look like

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

C# Solutions


Solution 1 - C#

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

where *.* is pattern to match files

If the Directory is also needed you can go like this:

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

Solution 2 - C#

Directory.GetFileSystemEntries exists in .NET 4.0+ and returns both files and directories. Call it like so:

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

Note that it won't cope with attempts to list the contents of subdirectories that you don't have access to (UnauthorizedAccessException), but it may be sufficient for your needs.

Solution 3 - C#

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

Note: the function shows only names without relative paths.

Solution 4 - C#

Use the GetDirectories and GetFiles methods to get the folders and files.

Use the SearchOption AllDirectories to get the folders and files in the subfolders also.

Solution 5 - C#

I am afraid, the GetFiles method returns list of files but not the directories. The list in the question prompts me that the result should include the folders as well. If you want more customized list, you may try calling GetFiles and GetDirectories recursively. Try this:

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

Tip: You can use FileInfo and DirectoryInfo classes if you need to check any specific attribute.

Solution 6 - C#

I use the following code with a form that has 2 buttons, one for exit and the other to start. A folder browser dialog and a save file dialog. Code is listed below and works on my system 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);
            }
        }
    }
}

Solution 7 - C#

You could use FindFirstFile which returns a handle and then recursively cal a function which calls FindNextFile.This is a good aproach as the structure referenced would be filled with various data such as alternativeName,lastTmeCreated,modified,attributes etc

But as you use .net framework, you would have to enter the unmanaged area.

Solution 8 - C#

Some improved version with max lvl to go down in directory and option to exclude folders:

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

input directory:

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

output of the function (content of folder5 is excluded due to lvl limit and content of folder3 is excluded because it is in excludedFolders array):

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

Solution 9 - C#

A late answer, but I think someone might benefit from it. A stack-based iterative version starter with support for error handling and returning relative paths:

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

Solution 10 - C#

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

Solution 11 - C#

If you don't have access to a subfolder inside the directory tree, Directory.GetFiles stops and throws the exception resulting in a null value in the receiving string[].

Here, see this answer https://stackoverflow.com/a/38959208/6310707

It manages the exception inside the loop and keep on working untill the entire folder is traversed.

Solution 12 - C#

The following example the fastest (not parallelized) way list files and sub-folders in a directory tree handling exceptions. It would be faster to use Directory.EnumerateDirectories using SearchOption.AllDirectories to enumerate all directories, but this method will fail if hits a UnauthorizedAccessException or PathTooLongException.

Uses the generic Stack collection type, which is a last in first out (LIFO) stack and does not use recursion. From https://msdn.microsoft.com/en-us/library/bb513869.aspx, allows you to enumerate all sub-directories and files and deal effectively with those exceptions.

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

Solution 13 - C#

the logical and ordered way:

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

Solution 14 - C#

With this you can just run them and chosse the sub folder when console run

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

and this the patchar for XML export

using System.Xml.Serialization;

namespace data.Patcher
{
    public class MetaFile
    {

        [XmlArray("Tasks")]
        public MetaFileEntry[] Tasks
        {
            get;
            set;
        }

        [XmlAttribute("checksum")]
        public string FolderChecksum
        {
            get;
            set;
        }
    }
}

Solution 15 - C#

Please try the below code to read all directories and sub-directories with files

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

The "ReadDirectories" method is called till the last directory is scanned.

Solution 16 - C#

Create List Of String

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

}

Solution 17 - C#

A littlebit simple and slowly but working!! if you do not give a filepath basicly use the "fixPath" this is just example.... you can search the correct fileType what you want, i did a mistake when i chosen the list name because the "temporaryFileList is the searched file list so carry on that.... and the "errorList" is speaks for itself

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionderp_in_mouthView Question on Stackoverflow
Solution 1 - C#Ruslan F.View Answer on Stackoverflow
Solution 2 - C#Alastair MawView Answer on Stackoverflow
Solution 3 - C#Evan DangolView Answer on Stackoverflow
Solution 4 - C#GuffaView Answer on Stackoverflow
Solution 5 - C#Krishna SarmaView Answer on Stackoverflow
Solution 6 - C#GarryView Answer on Stackoverflow
Solution 7 - C#Reznicencu BogdanView Answer on Stackoverflow
Solution 8 - C#brainoverflow98View Answer on Stackoverflow
Solution 9 - C#Alexandru ClonțeaView Answer on Stackoverflow
Solution 10 - C#aahView Answer on Stackoverflow
Solution 11 - C#ShubhamView Answer on Stackoverflow
Solution 12 - C#MarkusView Answer on Stackoverflow
Solution 13 - C#SaschaView Answer on Stackoverflow
Solution 14 - C#Smar tsView Answer on Stackoverflow
Solution 15 - C#Sadik AliView Answer on Stackoverflow
Solution 16 - C#رضا جونView Answer on Stackoverflow
Solution 17 - C#PekaView Answer on Stackoverflow