views:

81

answers:

3

The following works, but I figured - since it is all based on IEnumerable, Linq can come handy here is well. By the way, is there an equivalent to Directory.GetFiles() which would return an IEnumerable instead of the array? If it exists, then would it make the code run any faster? The last part of the question is inspired by Python language which favors lightweight generators over concrete lists.

    private IEnumerable<string> getFiles(string strDirectory, bool bCompressedOnly)
    {
        foreach (var strFile in Directory.GetFiles(strDirectory))
        {
            // Don't add any existing Zip files since we don't want to delete previously compressed files.
            if (!bCompressedOnly || Path.GetExtension(strFile).ToLower().Equals(".zip"))
            {
                yield return strFile;
            }
        }

        foreach (var strDir in Directory.GetDirectories(strDirectory))
        {
            foreach (var strFile in getFiles(strDir, bCompressedOnly))
            {
                yield return strFile;
            }
        }
    }
+2  A: 

I take zero credit because I had ReSharper do it for me, but here's what it suggested.

private IEnumerable<string> getFiles(string strDirectory, bool bCompressedOnly) {
    foreach (var strFile in Directory.GetFiles(strDirectory).Where(strFile => !bCompressedOnly || Path.GetExtension(strFile).ToLower().Equals(".zip"))) {
        yield return strFile;
    }

    foreach (var strFile in Directory.GetDirectories(strDirectory).SelectMany(strDir => getFiles(strDir, bCompressedOnly))) {
        yield return strFile;
    }
}

They're all arbitrary changes and in some ways I think (at least in the first loop) they obfuscate the logic a bit, but take it or leave it. Also, check out ReSharper if you haven't already. :)

Nathan Taylor
Yeah, after trying to read this I'd definitely prefer the original code, but this *does* answer the question.
FrustratedWithFormsDesigner
And so we can see, sometimes more *is* better. Although, the second loop is actually quite a bit cleaner. Maybe use that one and leave the first one the way it is.
Nathan Taylor
+7  A: 

I don't think I prefer this but...

return (
        from file in Directory.GetFiles(strDirectory)
        where !bCompressedOnly
            || Path.GetExtension(file).ToLower().Equals(".zip")
        select file
    ).Concat(
        from directory in Directory.GetDirectories(strDirectory)
        from file in getFiles(directory, bCompressedOnly)
        select file
    );

New in .NET 4:

private static IEnumerable<string> getFiles(string strDirectory,
    bool bCompressedOnly)
{
    return Directory.EnumerateFiles(strDirectory,
        bCompressedOnly ? "*.zip" : "*.*", SearchOption.AllDirectories);
}
Daniel Renshaw
SearchOption is available before .NET 4
tafa
Directory.EnumerateFiles is new in .NET 4 : http://msdn.microsoft.com/en-us/library/dd383571.aspx
Daniel Renshaw
Is file name search pattern case insensitive? Also ... if a file happens to be without an extension, does `"*"` suffice for a search pattern?
Hamish Grubijan
Yes, it's insensitive (assuming you're running on Windows where all filenames are insensitive)
Daniel Renshaw
Searching for `*.*` will find all files, even those without an extension (I've tested this).
Daniel Renshaw
Hurray for .NET 4!
Nathan Taylor
I am looking forward to .Net 10.0
Hamish Grubijan
+2  A: 

There is a GetFiles overload method of Directory which takes a search pattern string and a System.IO.SearchOption enumeration. One of SearchOption value is AllDirectories. If it is used, you would get rid of the second loop of your method.

private IEnumerable<string> getFiles(string strDirectory, bool bCompressedOnly)
{
    foreach (var strFile in Directory.GetFiles(strDirectory, bCompressedOnly ? "*.zip" : "*.*", SearchOption.AllDirectories))
    {
        yield return strFile;
    }
}
tafa
AllDirectories means search recursively, it doesn't actually return directories.
ck
@ck, neither does this method returns directories.
tafa
@ck, the OP's code only returns files, not directories, so it sounds like `AllDirectories` is exactly what's needed.
Sam
May I have code that does the same please?
Hamish Grubijan