Directory.GetFiles of certain extension
Asked Answered
C

3

78

Is there a way to simplify this linq expression, or is there a better way of doing this?

Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories)
         .Where(s => s.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
                     s.EndsWith(".gif", StringComparison.OrdinalIgnoreCase) ||
                     s.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
                     ...);

Basically I want to return all files of a certain extension. Unfortunately, this method isn't very flexible. I'd rather be able to add extensions to a list and have Directory.GetFiles return those extensions. Is that possible?

Communard answered 9/11, 2012 at 2:0 Comment(2)
Duplicate: #163662Powel
Possible duplicate of Can you call Directory.GetFiles() with multiple filters?Theran
E
127

If you would like to do your filtering in LINQ, you can do it like this:

var ext = new List<string> { "jpg", "gif", "png" };
var myFiles = Directory
    .EnumerateFiles(dir, "*.*", SearchOption.AllDirectories)
    .Where(s => ext.Contains(Path.GetExtension(s).TrimStart(".").ToLowerInvariant()));

Now ext contains a list of allowed extensions; you can add or remove items from it as necessary for flexible filtering.

Edmondson answered 9/11, 2012 at 2:5 Comment(5)
I can perform tests, but do you know which one would be more efficient?Communard
Interesting that it works... From the documentation on GetFiles, it doesn't seem like it would accept the | like you would expect from a regex. The docs say it only recognizes * and ?, but hey, if it works, it works =)Amaral
Note: This doesn't seem to work on Win7 x64 running .NET 4.5. Throws Illegal characters in path due to the pipe.Erb
@SimonWhitehead Never mind, I misinterpreted a piece of code in a post on Microsoft's web site, where a similarly-named method has been interpreting the pipes internally. I removed the non-working part of the solution (and SSL checked only the first one).Edmondson
Note for the passerby: you might get a performance boost out of the newer .NET 4.0 Directory.EnumerateFiles as mentioned in answer by @nekizalbSegmental
A
34

Doesn't the Directory.GetFiles(String, String) overload already do that? You would just do Directory.GetFiles(dir, "*.jpg", SearchOption.AllDirectories)

If you want to put them in a list, then just replace the "*.jpg" with a variable that iterates over a list and aggregate the results into an overall result set. Much clearer than individually specifying them. =)

Something like...

foreach(String fileExtension in extensionList){
    foreach(String file in Directory.GetFiles(dir, fileExtension, SearchOption.AllDirectories)){
        allFiles.Add(file);
    }
}

For .NET 4+: if your directories are large, using EnumerateFiles instead of GetFiles can potentially be more efficient

Amaral answered 9/11, 2012 at 2:4 Comment(3)
Please be aware of the fact that while using wildcard * there is always chance that you can mess up the intended logic . For instance you have two files Test1.xls and Test2.xlsx and if you use filter *.xls to filter out xls file , Directory.GetFiles ** returns both xls as well as xlsx files **. [Read MSDN for more info]: msdn.microsoft.com/en-us/library/ms143316%28v=vs.110%29.aspxGaidano
effectively, xls and xlsx are the same file that modern day Excel can read?Ford
@Ford It's not an issue for Excel, it's an issue for other systems that try to read Excel data. But yes it's an exceedingly rare edge case.Cohen
M
13

I would have done using just a single line like:

List<string> imageFiles = Directory.GetFiles(dir, "*.*", SearchOption.AllDirectories).Where(file => new string[] { ".jpg", ".gif", ".png" }.Contains(Path.GetExtension(file))).ToList();
Morphine answered 6/6, 2016 at 10:8 Comment(1)
This works, of course, but the lambda expression you pass to .Where() will create one string[] every time it's invoked; that is, for every file under dir. If dir is, say, @"C:\" then this could potentially create tens or hundreds of thousands of short-lived "garbage" arrays. I definitely think it'd be worth it to define your array outside of .Where(), even if it means having to write that dreaded second line of code.Annabellannabella

© 2022 - 2024 — McMap. All rights reserved.