67

I have a method that will iterate through a folder and all of its subfolders and get a list of the file paths. However, I could only figure out how to create it and add the files to a public List, but not how to return the list. Here's the method:

public List<String> files = new List<String>();

private void DirSearch(string sDir)
    {
        try
        {
            foreach (string f in Directory.GetFiles(sDir))
            {
                files.Add(f);
            }
            foreach (string d in Directory.GetDirectories(sDir))
            {
                DirSearch(d);
            }
        }
        catch (System.Exception excpt)
        {
            MessageBox.Show(excpt.Message);
        }
    }

So, i just call DirSearch() at some point in my code and it 'fills' the list with the paths, but I want to be able to use it multiple times to create different lists with different directories, etc.

Wilson
  • 8,570
  • 20
  • 66
  • 101
  • Why don't you define the List 'files' variable within 'DirSearch' and have 'DirSearch' return 'files'? – Kim Hansson Jan 13 '13 at 16:41
  • Thanks works great. This is where C# differs from other languages like Java where it listsAllFiles or readdir for nodejs. C# has separate methods for files and directories. Thank you :-) – Spencer Davis Sep 10 '21 at 19:37

9 Answers9

180

You can use Directory.GetFiles to replace your method.

 Directory.GetFiles(dirPath, "*", SearchOption.AllDirectories)
Tilak
  • 30,108
  • 19
  • 83
  • 131
  • If at any point, this throws an exception due to file/folder permissions, the whole statement won't work. Right? (That was why I originally wrote a helper method) – Wilson Jan 13 '13 at 16:40
  • 9
    That is correct, But you are using `Directory.GetFiles`, and `Directory.GetDirectory` in helper method that has the same issues. The helper method is better in a sense, it will result more entries, but chances are it will swallow some also (that has the access rights). Better way is to use `Directory.EnumerateDirectories` and `Directory.EnumerateFiles` that will give you sequential access to the iterator, and then you can check permission for each file/folder. – Tilak Jan 13 '13 at 16:46
61
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.

Community
  • 1
  • 1
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
26

Simply use this:

public static List<String> GetAllFiles(String directory)
{
    return Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories).ToList();
}

And if you want every file, even extensionless ones:

public static List<String> GetAllFiles(String directory)
{
    return Directory.GetFiles(directory, "*", SearchOption.AllDirectories).ToList();
}
Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98
15

you can use something like this :

string [] filePaths = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);

instead of using "." you can type the name of the file or just the type like "*.txt" also SearchOption.AllDirectories is to search in all subfolders you can change that if you only want one level more about how to use it on here

sam
  • 171
  • 2
  • 4
3

I am not sure of why you're adding the strings to files, which is declared as a field rather than a temporary variable. You could change the signature of DirSearch to:

private List<string> DirSearch(string sDir)

And, after the catch block, add:

return files;

Alternatively, you could create a temporary variable inside of your method and return it, which seems to me the approach you might desire. Otherwise, each time you call that method, the newly found strings will be added to the same list as before and you'll have duplicates.

e_ne
  • 8,340
  • 32
  • 43
3

This is for anyone that is trying to get a list of all files in a folder and its sub-folders and save it in a text document. Below is the full code including the “using” statements, “namespace”, “class”, “methods” etc. I tried commenting as much as possible throughout the code so you could understand what each part is doing. This will create a text document that contains a list of all files in all folders and sub-folders of any given root folder. After all, what good is a list (like in Console.WriteLine) if you can’t do something with it. Here I have created a folder on the C drive called “Folder1” and created a folder inside that one called “Folder2”. Next I filled folder2 with a bunch of files, folders and files and folders within those folders. This example code will get all the files and create a list in a text document and place that text document in Folder1. Caution: you shouldn’t save the text document to Folder2 (the folder you are reading from), that would be just bad practice. Always save it to another folder.
I hope this helps someone down the line.

using System;
using System.IO;

namespace ConsoleApplication4
{
    class Program
    {
        public static void Main(string[] args)
        {
            // Create a header for your text file
            string[] HeaderA = { "****** List of Files ******" };
            System.IO.File.WriteAllLines(@"c:\Folder1\ListOfFiles.txt", HeaderA);

            // Get all files from a folder and all its sub-folders. Here we are getting all files in the folder
            // named "Folder2" that is in "Folder1" on the C: drive. Notice the use of the 'forward and back slash'.
            string[] arrayA = Directory.GetFiles(@"c:\Folder1/Folder2", "*.*", SearchOption.AllDirectories);
            {
                //Now that we have a list of files, write them to a text file.
                WriteAllLines(@"c:\Folder1\ListOfFiles.txt", arrayA);
            }

            // Now, append the header and list to the text file.
            using (System.IO.StreamWriter file =
                new System.IO.StreamWriter(@"c:\Folder1\ListOfFiles.txt"))
            {
                // First - call the header 
                foreach (string line in HeaderA)
                {
                    file.WriteLine(line);
                }

                file.WriteLine(); // This line just puts a blank space between the header and list of files. 


                // Now, call teh list of files.
                foreach (string name in arrayA)
                {
                    file.WriteLine(name);
                }

            }
          }


        // These are just the "throw new exception" calls that are needed when converting the array's to strings. 

        // This one is for the Header.
        private static void WriteAllLines(string v, string file)
        {
            //throw new NotImplementedException();
        }

        // And this one is for the list of files. 
        private static void WriteAllLines(string v, string[] arrayA)
        {
            //throw new NotImplementedException();
        }



    }
}
Aubrey Love
  • 946
  • 6
  • 12
2
String[] allfiles = System.IO.Directory.GetFiles("path/to/dir", "*.*", System.IO.SearchOption.AllDirectories);
Tunaki
  • 132,869
  • 46
  • 340
  • 423
Veera Induvasi
  • 822
  • 7
  • 19
1

A LINQ solution:

public IEnumerable<FileInfo> DirSearch(string sDir){
            var directoryInfo = new DirectoryInfo(sDir);
            return directoryInfo.GetDirectories()
                .SelectMany(directory => directory.GetFiles());
}

This will return FileInfos and not strings, because they are easier to work with I think.

Anno
  • 761
  • 1
  • 10
  • 22
0

Try this
class Program { static void Main(string[] args) {

        getfiles get = new getfiles();
        List<string> files =  get.GetAllFiles(@"D:\Rishi");

        foreach(string f in files)
        {
            Console.WriteLine(f);
        }


        Console.Read();
    }


}

class getfiles
{
    public List<string> GetAllFiles(string sDirt)
    {
        List<string> files = new List<string>();

        try
        {
            foreach (string file in Directory.GetFiles(sDirt))
            {
                files.Add(file);
            }
            foreach (string fl in Directory.GetDirectories(sDirt))
            {
                files.AddRange(GetAllFiles(fl));
            }
        }
        catch (Exception ex)
        {

            Console.WriteLine(ex.Message);
        }



        return files;
    }
}
Ris
  • 7
  • 1