Recusive GetFiles for DirectoryInfo via a C# Iterator

I have been working on a project using C# Express and so I have been playing around with some of the new C# 2.0 features. In my project I had a need to get all the files of a particular type in a given directory including all sub-directories. The DirectoryInfo class has a method GetFiles that takes a search pattern (ie "*.exe") but it only searches that directory it doesn't search sub-directories. So I figured this would be a good chance for me to play with these new things called iterators. At any rate I wrote a recursive version of GetFiles using an iterator so that I could do a simple foreach loop to get all the files recursively.

public static IEnumerable<FileInfo> GetFilesRecursive(DirectoryInfo dirInfo)
{
    return GetFilesRecursive(dirInfo, "*.*");
}
public static IEnumerable<FileInfo> GetFilesRecursive(DirectoryInfo dirInfo, string searchPattern)
{
    foreach (DirectoryInfo di in dirInfo.GetDirectories())
        foreach (FileInfo fi in GetFilesRecursive(di, searchPattern))
            yield return fi;
        
    foreach (FileInfo fi in dirInfo.GetFiles(searchPattern))
        yield return fi;
}

13 Comments

  • Nice example.



    Two nitpicks:

    First, your source code coloring tool doesn't consider yield to be a keyword.



    Second, I think it is slightly better to yield the files first, before recursing into the directories.



    Told you it was nitpicking :).

  • First: Yeah you are right I need to update the keywords in my code colorizer. I noticed that after I posted it but I was to lazy to fix it yet.



    Second: It just depends on whether or not you want to do a depth vs breadth first search, I just chose to do a depth but as you point out you can easily change it by switching the loops around. I suppose if you have a really deep file structure and you are searching for a file a breadth-first search might be better.

  • I think you'd really drive the point home by showing the non-interator code to do the same thing.

  • Ok, now you got me curios!



    Stephane, Wes, why would it be slightly better to put the file iteration first? (Asking humbly, certainly not trying to be smart-allecky here!)



    Usually, in my code, some other little feature that I want to implement or factor that I have to take into consideration will imply that I have to put the &quot;shallow&quot; iteration before or after the recursive one. In a case as the one above, where there's no factors to decide this, I would have thought it didn't really matter if you put it first or last!?



    I love nitpicking, and I'm not arguing against you, I'd just really like to improve my understanding! :-)



    /Mats

  • Mats,



    If you are going to do something with all the items and the order doesn't matter to you than I would say that it doesn't matter which you put first.



    One example of where it might matter is if you are searching for a file and you have some insight that it should be less than X directories deep. It that case you would probably search the files first then go deeper, that way you would find the file faster and you could terminate your loop as soon as you find your file.

  • The font of your blog is really really really (once more ;-) really annoying. What about something more standard like Arial or Verdana or even Times.



    To me, it's much more readable and way more professional...

  • I agree with Uwe on the font, it reminds me of bad desktop publishing software from grade school.



    Stick with ms sans or arial, comic sans is too tacky.

  • Why not use something like Directory.GetFiles(currFolder, "*", SearchOption.AllDirectories) and that's it?

  • You could using Directory.GetFiles, however the purpose of this example is to show how to create an iterator. Also I don't believe Directory.GetFiles is implmented as an iterator so you would have to wait until all the files have been gathered before doing any work.

  • And I get this error when trying to use the code (VS2005 vMicrosoft Visual Studio 2005
    Version 8.0.50727.42):

    CS0308: The non-generic type 'System.Collections.IEnumerable' cannot be used with type arguments

  • Sven - It sounds like you have the statement using System.Collections; instead of using System.Collections.Generic; at the top of your file.

  • Sorry to ask such a newbie question, but how can I output the folder and file name using the code above?

  • I'm trying to iterate through a folder structure on my local machine and create an xml representation of it so I'm hoping that this method will help, I'm just not sure how to use it?

Comments have been disabled for this content.