R. Martin
R. Martin

Reputation: 87

Count of files in C# with LINQ

Env: C#, VStudio 2013, 4.5 Framework, Winforms

Goal : Getting the number of files (Count) in a folder and subfolder that match extensions stored in an array of string. The array of extension can be with the "." of not. {".dat","txt",".msg"}

What i've done so far : When I'm having the "." in the array of extensions, everything is working : {".dat",".txt",".msg"}

I have tried the Replace but it's always returning 0.

The working code (Only if always with the "." in array of string):

string[] ext= new string[] { ".txt", ".msg", ".dat" };
totalFilesInTN = Directory.EnumerateFiles(dlg1.SelectedPath, "*.*", SearchOption.AllDirectories)
                          .Count(s => ext.Any(s1 => s1 == Path.GetExtension(s)));

The not working code (always return 0) :

string[] ext= new string[] { "txt", ".msg", "dat" };
totalFilesInTN = Directory.EnumerateFiles(dlg1.SelectedPath, "*.*", SearchOption.AllDirectories)
                          .Count(s => ext.Any(s1 => s1 == Path.GetExtension(s).Replace(".", "")));

Upvotes: 5

Views: 890

Answers (4)

fg_garda
fg_garda

Reputation: 116

Then GetExtension() method always includes the ".", so you have to normalize the extension that you are checking.

string[] extensions = new string[] { "docx", ".msg", "pdf" };
var filesCount = Directory.EnumerateFiles(folderPath, "*.*", SearchOption.AllDirectories)
 .Count(filePath => extensions.Any(e => (e.StartsWith(".") ? e : "." + e) == Path.GetExtension(filePath)));

But it's better normalize the collection only once at the beginning.

Upvotes: 0

Steve Mitcham
Steve Mitcham

Reputation: 5313

The documentation for the Path.GetExtension method states that the return value is:

The extension of the specified path (including the period "."), or null, or String.Empty.

Your second block of code strips off the '.' so none of the elements will match. Therefore, go the opposite way with your list of extensions and just ensure that the start of each extension has a '.' and then use your first block of code.

string[] ext = new string[] {"txt", ".msg", ".dat" }
    .Select(x => x.StartsWith(".") ? x : "." + x)
    .ToArray();

Upvotes: 6

Tim Schmelter
Tim Schmelter

Reputation: 460208

It's not working because you have to remove the dots from both extensions. The Path.GetExtension always prepends the dot. But it's you extension array that can contain extensions without. So you have to remove the dot from both if you want to compare them:

So instead of

....Count(s => ext.Any(s1 => s1 == Path.GetExtension(s).Replace(".", "")));

this:

....Count(s => ext.Any(s1 => si.Replace(".", "") == Path.GetExtension(s).Replace(".", "")));

But as others have mentioned, fix the invalid source, modify the array that it only contains extensions with dot. Then it's much more readable and efficient.

You can also use Contains:

....Count(s => ext.Contains(Path.GetExtension(s)));

Upvotes: 1

Adil
Adil

Reputation: 148150

You need to replace the . dot in both the array ext element and the directory item. You need to use .Replace with s1 as well to compare the array and file extension after removing dot from each.

string[] ext= new string[] { "txt", ".msg", "dat" };
totalFilesInTN = Directory.EnumerateFiles(dlg1.SelectedPath, "*.*", SearchOption.AllDirectories)
                 .Count(s => ext.Any(s1 => s1.Replace(".", "") == Path.GetExtension(s).Replace(".", "")));

Upvotes: 1

Related Questions