A convenient method for beginners to get a list of all files and directories

Using .NET 3.0, I have a method below that correctly returns a collection of all the files and directories (and subdirectories) of the specified directory. I would like, if possible, stupid to use it, to use only designs with which I am very comfortable. In particular, here is what I do not understand:

1. IEnumerable<FileSystemInfo>: I'd like to return List<FileSystemInfo> instead 2. Stack<FileSystemInfo>: I'd list to use List<FileSystemInfo> instead. 3. yield return: I've never used this before 

.

 public static IEnumerable<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) { DirectoryInfo dirInfo = new DirectoryInfo( dir ); Stack<FileSystemInfo> stack = new Stack<FileSystemInfo>(); stack.Push( dirInfo ); while ( dirInfo != null || stack.Count > 0 ) { FileSystemInfo fileSystemInfo = stack.Pop(); DirectoryInfo subDirectoryInfo = fileSystemInfo as DirectoryInfo; if ( subDirectoryInfo != null ) { yield return subDirectoryInfo; foreach ( FileSystemInfo fsi in subDirectoryInfo.GetFileSystemInfos() ) { stack.Push( fsi ); } dirInfo = subDirectoryInfo; } else { yield return fileSystemInfo; dirInfo = null; } } } 

.

One could argue that I just need to improve the code above, but this is not what I am shooting today.

Thanks in advance

+4
source share
6 answers

I believe you are looking for an existing GetFileSystemInfos method (string, SearchOptions). If you specify AllDirectories as the value of SearchOptions, it will recursively search for the transferred in the folder.

Example:

 public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) { DirectoryInfo info = new DirectoryInfo(dir); FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories); return new List<FileSystemInfo>(all); } 

If you want to write a long way, but you can do the following

 public static List<FileSystemInfo> GetAllFilesAndDirectories ( string dir ) { int i = 0; List<DirectoryInfo> toProcess = new List<DirectoryInfo>(); List<FileSystemInfo> list = new List<FileSystemInfo>(); toProcess.Add(new DirectoryInfo(dir)); while ( i < toProcess.Count ) { DirectoryInfo curDir = toProcess[i]; foreach ( FileSystemInfo curFile in curDir.GetFileSystemInfos() ) { list.Add(curFile); DirectoryInfo maybe = curFile as DirectoryInfo; if ( maybe != null ) { toProcess.Add(maybe); } i++; } return list; } FileSystemInfo[] all = info.GetFileSystemInfos("*", SearchOptions.AllDirectories); return new List<FileSystemInfo>(all); } 
0
source

Here is the shortest way I can think of:

 static List<FileSystemInfo> GetAllFilesAndDirectories(string dir) { DirectoryInfo dirInfo = new DirectoryInfo(dir); List<FileSystemInfo> allFilesAndDirectories = new List<FileSystemInfo>(); allFilesAndDirectories.AddRange(dirInfo.GetFiles("*", SearchOption.AllDirectories)); allFilesAndDirectories.AddRange(dirInfo.GetDirectories("*", SearchOption.AllDirectories)); return allFilesAndDirectories; } 

It will return a list of all files and directories at all levels, starting from the given path. The order in which they will be returned will be all files, and then all directories.

+2
source
  public List<Object> GetFilesAndDirectories(string path) { List<Object> lst = new List<Object>(); string[] dirs = null; try { dirs = Directory.GetDirectories(path); } catch (Exception e) { Console.WriteLine(e.Message); } foreach (string d in dirs) { string[] files = null; try { files = Directory.GetFiles(d); } catch (Exception e) { Console.WriteLine(e.Message); } foreach (string f in files) { lst.Add(f); } lst.Add(d); lst.AddRange(GetFilesAndDirectories(d)); } return lst; } List<Object> stuff = GetFilesAndDirectories(someRoot); 
+1
source

You asked, in particular, "omit this." I think the other two answers are very good, but here is another way to do this with an even simpler, clearer concept at the beginning of the level code.

http://support.microsoft.com/kb/303974

Edit

I know this is not 3.0, but it is still a tried, tested, and clear way to do this.

0
source

If you want a "beginner-friendly method", I can suggest the bobbymcr method .

But if you want to maintain your code structure, I will reproduce below the code that I posted in your next question :

 static IEnumerable<FileSystemInfo> GetAllFilesAndDirectories(string path) { string currentDirectory = ""; string[] files = Directory.GetFiles( // skip empty subfolders path, "*.*", SearchOption.AllDirectories); foreach (string file in files) { if(currentDirectory != Path.GetDirectoryName(file)) { // First time in this directory: return it currentDirectory = Path.GetDirectoryName(file); yield return new DirectoryInfo(currentDirectory); } yield return new FileInfo(file); } } 
0
source

I think that in terms of code readability, it's best to write a recursive function. A recursive function is one that calls itself until it reaches a point where it does not need to call any other function.

To illustrate, the factorial n is written as n! and defined as 1 x 2 x 3 x ... xn (where n is a positive integer), can be easily determined recursively as follows.

 public int factorial(int n) { if (n < 0) { throw new Exception("A factorial cannot be calculated for negative integers."); } if (n == 0 || n == 1) { // end condition, where we do not need to make a recursive call anymore return 1; } else { // recursive call return n * factorial(n - 1); } } 

NB: 0! and 1! defined as 1.

Similarly, the method of listing all files and folders by a given path can also be defined recursively. This is because files and folders have a recursive structure.

Therefore, a method like the following will work:

 public static List<FileSystemInfo> GetAllFilesAndFolders(string folder) { // NOTE : We are performing some basic sanity checking // on the method formal parameters here if (string.IsNullOrEmpty(folder)) { throw new ArgumentException("An empty string is not a valid path.", "folder"); } if (!Directory.Exists(folder)) { throw new ArgumentException("The string must be an existing path.", "folder"); } List<FileSystemInfo> fileSystemInfos = new List<FileSystemInfo>(); try { foreach (string filePath in Directory.GetFiles(folder, "*.*")) { // NOTE : We will add a FileSystemInfo object for each file found fileSystemInfos.Add(new FileInfo(filePath)); } } catch { // NOTE : We are swallowing all exceptions here // Ideally they should be surfaced, and at least logged somewhere // Most of these will be security/permissions related, ie, // the Directory.GetFiles method will throw an exception if it // does not have security privileges to enumerate files in a folder. } try { foreach (string folderPath in Directory.GetDirectories(folder, "*")) { // NOTE : We will add a FileSystemInfo object for each directory found fileSystemInfos.Add(new DirectoryInfo(folderPath)); // NOTE : We will also add all FileSystemInfo objects found under // each directory we find fileSystemInfos.AddRange(GetAllFilesAndFolders(folderPath)); } } catch { // NOTE : We are swallowing all exceptions here // Ideally they should be surfaced, and at least logged somewhere // Most of these will be security/permissions related, ie, // the Directory.GetDirectories method will throw an exception if it // does not have security privileges to enumerate files in a folder. } return fileSystemInfos; } 

It should be noted that this method will "walk" through the entire directory structure under the folder and will NOT return until it "destroys" all the heredity. Thus, it may take a long time to return if there are many objects that can be found.

Another thing to note is that the readability of this method can be further improved with the help of Lambda expressions and extension methods.

Note. The problem with using Directory.GetFiles and Directory.GetDirectories for recursing subfolders is that if there are any exceptions (for example, related to security permissions), the method will return nothing, while recursing manually allows you to handle these exceptions and still get a set of files back.

0
source

All Articles