Reputation: 3476
I want to write a function that filter files in directory. The method received path, list of tokens the file must be contain and list of token that should not be in the file.
my code is like this:
private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain)
{
String[] files = Directory.GetFiles(path).Where(f => (contain.All(f.Contains)) && (!notContain.Any(f.Contains))).ToArray();
//String[] files = Directory.GetFiles(path).Where(f => f.IndexOf(contain.All(f.Contains), 0, StringComparison.CurrentCultureIgnoreCase) != -1).ToArray();
return files;
}
I try to receive list of files that match the criteria and I succeed to obtain correct list but just for sensitive tokens.
(In the commend you can see my try to get one for case insensitive but there is an error...)
How can I check if the filename contain all string in the list in case insensitive ?
Here's an example. Let's say I have the follow files in my directory:
proj_debug_3.2.0.txt
proj_release_3.2.1.txt
proj_release_3.2.1_useThis_TRY.txt
proj_release_3.2.1_UseThis.txt
so call to
enumerateFilesByFilter(path, new List<String> { "Release", "useThis" }, new List<String> {"try", "debug" });
should return proj_release_3.2.1_UseThis.txt
file
Upvotes: 0
Views: 1002
Reputation: 3476
Finally I found solution (the solution is ugly but working):
private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain)
{
String[] files = Directory.EnumerateFiles(path).Where(f => (contain.All(c => f.ToLower().Contains(c.ToLower()))) &&
(!notContain.Any(c => f.ToLower().Contains(c.ToLower())) )).ToArray();
return files;
}
Upvotes: 0
Reputation: 411
At first, I'd define a new extension method for case-insensitive search:
public static class StringExtensions
{
public static bool Contains(this string source, string pattern, StringComparison comparision)
{
return source.IndexOf(pattern, comparision) >= 0;
}
}
Then rewrite your method like this:
public static IEnumerable<string> EnumerateFilesByFilter(String path, List<String> include, List<String> exclude)
{
return Directory.EnumerateFiles(path).
Where(f => include.All(i => f.Contains(i, StringComparison.OrdinalIgnoreCase))).
Where(f => exclude.All(i => !f.Contains(i, StringComparison.OrdinalIgnoreCase)));
}
Please note, that I used IEnumerable as return type and Directory.EnumerateFiles() for the file system listing. This way the whole operation is much more efficient, and using only enumerables.
Upvotes: 1
Reputation: 460108
This should work as desired:
private String[] enumerateFilesByFilter(String path, List<String> contain, List<String> notContain)
{
String[] files = Directory.EnumerateFiles(path)
.Where(f => contain.All(s => s.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0)
&& !notContain.Any(s => s.IndexOf(f, StringComparison.CurrentCultureIgnoreCase) >= 0))
.ToArray();
return files;
}
Note that i use Directory.EnumerateFiles
instead of Directory.GetFiles
because it can start processing before all files are returned as opposed to GetFiles
which first creates an array of all files.
Maybe you should also consider to use System.IO.Path.GetFileName(f)
to check only the file-name instead of the full path.
Upvotes: 1