How to Recursively List All the Files in a Directory in C#

How to recursively list all the files in a directory in C#?

This article covers all you need. Except as opposed to searching the files and comparing names, just print out the names.

It can be modified like so:

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

Added by barlop

GONeale mentions that the above doesn't list the files in the current directory and suggests putting the file listing part outside the part that gets directories. The following would do that. It also includes a Writeline line that you can uncomment, that helps to trace where you are in the recursion that may help to show the calls to help show how the recursion works.

            DirSearch_ex3("c:\\aaa");
static void DirSearch_ex3(string sDir)
{
//Console.WriteLine("DirSearch..(" + sDir + ")");
try
{
Console.WriteLine(sDir);

foreach (string f in Directory.GetFiles(sDir))
{
Console.WriteLine(f);
}

foreach (string d in Directory.GetDirectories(sDir))
{
DirSearch_ex3(d);
}
}
catch (System.Exception excpt)
{
Console.WriteLine(excpt.Message);
}
}

Listing all files in a directory and sub-directories C#

SearchOption.AllDirectories might do the trick for you as it includes the current directory and all its subdirectories in a search operation. This option includes reparse points such as mounted drives and symbolic links in the search.

//Add System.IO then
String[] allfiles = Directory.GetFiles("DirectorytoSearch", "*", SearchOption.AllDirectories);

and to convert them to list

List<string> allfiles = Directory.GetFiles("DirectorytoSearch", "*",SearchOption.AllDirectories).ToList();

list recursively all files and folders under the given path?

Try something like this:

static void Main(string[] args)
{
DirSearch(@"c:\temp");
Console.ReadKey();
}

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

Searching for file in directories recursively

You could use this overload of Directory.GetFiles which searches subdirectories for you, for example:

string[] files = Directory.GetFiles(sDir, "*.xml", SearchOption.AllDirectories);

Only one extension can be searched for like that, but you could use something like:

var extensions = new List<string> { ".txt", ".xml" };
string[] files = Directory.GetFiles(sDir, "*.*", SearchOption.AllDirectories)
.Where(f => extensions.IndexOf(Path.GetExtension(f)) >= 0).ToArray();

to select files with the required extensions (N.B. that is case-sensitive for the extension).


In some cases it can be desirable to enumerate over the files with the Directory.EnumerateFiles Method:

foreach(string f in Directory.EnumerateFiles(sDir, "*.xml", SearchOption.AllDirectories))
{
// do something
}

Consult the documentation for exceptions which can be thrown, such as UnauthorizedAccessException if the code is running under an account which does not have appropriate access permissions.

If the UnauthorizedAccessException is a problem, then please see the fine answers at Directory.EnumerateFiles => UnauthorizedAccessException.

Method to get all files within folder and subfolders that will return a list

private List<String> DirSearch(string sDir)
{
List<String> files = new List<String>();
try
{
foreach (string f in Directory.GetFiles(sDir))
{
files.Add(f);
}
foreach (string d in Directory.GetDirectories(sDir))
{
files.AddRange(DirSearch(d));
}
}
catch (System.Exception excpt)
{
MessageBox.Show(excpt.Message);
}

return files;
}

and if you don't want to load the entire list in memory and avoid blocking you may take a look at the following answer.

Get file information from recursive folders

You can get most of these using the FileInfo class....

var info = new System.IO.FileInfo(@"c:\folder\file.ext");

It has properties for Length, CreationTime, LastAccessTime and LastWriteTime, to output them (for example) to the console, you could do...

Console.WriteLine("For file {0}", info.Name);
Console.WriteLine("Length is {0}", info.Length);
Console.WriteLine("Creation time is {0}", info.CreationTime);
Console.WriteLine("Last access time is {0}", info.LastAccessTime);
Console.WriteLine("Last write time is {0}", info.LastWriteTime);

To get the full filename, you can use GetFileNameWithoutExtension...

var fileName = System.IO.Path.GetFileNameWithoutExtension(@"c:\folder\file.ext")

filename will equal "file" in the above example.

Getting the description of a file extension is a bit more work, but can be done using SHGetFIleInfo, See this answer for details.

To integrate this with your current code (if you're not so worried about the file descriptions), you could change your GetFilesRecursively method to return a List<FileInfo>...

static List<FileInfo> GetFilesRecursively (string rootDirectory, string extension)

Update your opList variable accordingly...

List<FileInfo> opList = new List<FileInfo> ();

And then tweak your AddRange call to add FileInfo objects...

opList.AddRange (allFiles.Select(f => new FileInfo(f)));

Lastly, the type of subDirFileList will need to be changed as well, so a List<FileInfo>.

(I think that's everything!)

Recursively listing of files and folders in C#

The main problems with using recursion to do this is:

  1. If your tree has a depth that is too large you may not have enough stack space. While it would be uncommon to have that deep of a file system structure, it's not inconceivable.

  2. You are using more memory than needed, in that you're holding onto a lot of data in stack frames that you could potentially avoid.

As for the asymptotic complexity, you're performing one operation per node, regardless of it's size, so it's O(n), where n is all nodes, not the nodes at any given depth.

However, you can handle all of this much more effectively using the built in method to traverse the entire tree. It is going to be more efficient than a solution you'll come up with, even if yours is non-recursive, just use:

foreach(string file in Directory.EnumerateFiles(path, "*", 
SearchOption.AllDirectories))
{
System.IO.File.AppendAllText("e:\\personal\\tests.txt",
System.IO.Path.GetFileName(file) + ":" + rootFolder + "\n")
}

While that solution is likely not to use recursion, if you want to know how to write a non-recursive tree traversal yourself, you can use a general purpose method like this:

public static IEnumerable<T> Traverse<T>(
this IEnumerable<T> source
, Func<T, IEnumerable<T>> childrenSelector)
{
var stack = new Stack<T>(source);
while (stack.Any())
{
var next = stack.Pop();
yield return next;
foreach (var child in childrenSelector(next))
stack.Push(child);
}
}

In your case calling it could look something like this:

var allFiles = new[] { new DirectoryInfo(path) }
.Traverse(directory => directory.EnumerateDirectories())
.Select(directory => directory.EnumerateFiles());

Note that, while this is fine for traversing a tree that doesn't provide a built in way for a full traversal, this is generally not ideal for traversing the file system. You should use the first solution in that it has been highly optimized already for the special case of traversing a file system.

How to recursively list all the files in and get the files on going

If you mean that your method should return them one by one (assuming you understood EnumerateFiles() does that already). Use yield return:

public IEnumerable<string > Foo(string path)
{
foreach (string file in Directory.EnumerateFiles(
path, "*.*", SearchOption.AllDirectories))
{
// Add additional logic if you need here
yield return file;
}
}

That way, if you run with foreach on your method you'll get each file at a time and you can add additional logic in the method.



Related Topics



Leave a reply



Submit