How to filter Directory.EnumerateFiles with multiple criteria?
I created some helper methods to solve this which I blogged about earlier this year.
One version takes a regex pattern \.mp3|\.mp4
, and the other a string list and runs in parallel.
public static class MyDirectory
{ // Regex version
public static IEnumerable<string> GetFiles(string path,
string searchPatternExpression = "",
SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
Regex reSearchPattern = new Regex(searchPatternExpression, RegexOptions.IgnoreCase);
return Directory.EnumerateFiles(path, "*", searchOption)
.Where(file =>
reSearchPattern.IsMatch(Path.GetExtension(file)));
}
// Takes same patterns, and executes in parallel
public static IEnumerable<string> GetFiles(string path,
string[] searchPatterns,
SearchOption searchOption = SearchOption.TopDirectoryOnly)
{
return searchPatterns.AsParallel()
.SelectMany(searchPattern =>
Directory.EnumerateFiles(path, searchPattern, searchOption));
}
}
Directory.EnumerateFiles with special filters
Check extension length and last letter.
var files = Directory.EnumerateFiles(path, "*.*", SearchOption.AllDirectories)
.Where(s =>
{
string ext = Path.GetExtension(s);
return ext.Length == 4 && ext.EndsWith("b")
|| s.EndsWith(".in")
|| s.EndsWith(".txt");
});
Can you call Directory.GetFiles() with multiple filters?
For .NET 4.0 and later,
var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
For earlier versions of .NET,
var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
edit: Please read the comments. The improvement that Paul Farry suggests, and the memory/performance issue that Christian.K points out are both very important.
Exclude files from Directory.EnumerateFiles based on multiple criteria
Here's one way that uses FileInfo objects instead of strings. This eliminates all those Path calls, but should be easy to change if desired.
Dim ext() As String = {".jpg", ".gif", ".bmp", ".tif", ".png", ".tiff", ".jpeg"}
Dim exclusion() As String = {"thumb", "nothing", "empty"}
Dim fileArray = From chkFile As FileInfo In New DirectoryInfo(fpath).EnumerateFiles("*.*", SearchOption.TopDirectoryOnly)
Where ext.Contains(chkFile.Extension.ToLower(System.Globalization.CultureInfo.InvariantCulture)) _
And Not exclusion.Any(Function(x) chkFile.Name.ToLower(System.Globalization.CultureInfo.InvariantCulture).Contains(x))
Select chkFile
Multiple file-extensions searchPattern for System.IO.Directory.GetFiles
I believe there is no "out of the box" solution, that's a limitation of the Directory.GetFiles method.
It's fairly easy to write your own method though, here is an example.
The code could be:
/// <summary>
/// Returns file names from given folder that comply to given filters
/// </summary>
/// <param name="SourceFolder">Folder with files to retrieve</param>
/// <param name="Filter">Multiple file filters separated by | character</param>
/// <param name="searchOption">File.IO.SearchOption,
/// could be AllDirectories or TopDirectoryOnly</param>
/// <returns>Array of FileInfo objects that presents collection of file names that
/// meet given filter</returns>
public string[] getFiles(string SourceFolder, string Filter,
System.IO.SearchOption searchOption)
{
// ArrayList will hold all file names
ArrayList alFiles = new ArrayList();
// Create an array of filter string
string[] MultipleFilters = Filter.Split('|');
// for each filter find mathing file names
foreach (string FileFilter in MultipleFilters)
{
// add found file names to array list
alFiles.AddRange(Directory.GetFiles(SourceFolder, FileFilter, searchOption));
}
// returns string array of relevant file names
return (string[])alFiles.ToArray(typeof(string));
}
how to read all files in particular folder and filter more than one type?
You can concatenate two results like this
foreach (string file in Directory.EnumerateFiles(folderPath, "*.txt").Concat(Directory.EnumerateFiles(folderPath, "*.bmp")))
{
// (code here)
}
Or make it a function like so
IEnumerable<string> EnumerateFiles(string folderPath, params string[] patterns)
{
return patterns.SelectMany(pattern => Directory.EnumerateFiles(folderPath, pattern));
}
void Later()
{
foreach (var file in EnumerateFiles(".", "*.config", "*.exe"))
{
// (code here)
}
}
Directory.EnumerateFiles method: How to enumerate files in specified subdirectories?
Please consider some implementation like this one:
public static class Program
{
public static void Main()
{
var directoryPaths = new List<string>
{
@"C:\root\path_1",
@"C:\root\path_2",
@"C:\root\path_3"
// …
};
var searchPatterns = new List<string>
{
"*.jpg",
"*.gif"
};
var filePaths = directoryPaths
.SelectMany(directoryPath =>
EnumerateFiles(directoryPath, searchPatterns, SearchOption.AllDirectories))
.ToList()
.AsReadOnly();
// …
}
private static IEnumerable<string> EnumerateFiles(
string path,
IEnumerable<string> searchPatterns,
SearchOption searchOption)
{
var filePaths = searchPatterns.SelectMany(
searchPattern => Directory.EnumerateFiles(path, searchPattern, searchOption));
return filePaths;
}
}
Directory.EnumerateFiles with Take and Where
You need to reorder your statement to put the Where
before the Take
:
For Each _file As String In Directory.EnumerateFiles(Quellpfad, "*.rdy").Where(Function(item) item.Replace(Quellpfad, "").Length <= 11).Take(500)
The Where
returns all files matching your condition FIRST, and THEN limits those down to 500.
Related Topics
Cross Platform (PHP to C# .Net) Encryption/Decryption with Rijndael
Remove CSS Class in Code Behind
Does C# Have an Equivalent to JavaScript's Encodeuricomponent()
What's the Method Representation in Memory
Using Image Control in Wpf to Display System.Drawing.Bitmap
How to Encrypt Selected Properties When Serializing My Objects
How to Cast String to Int. Error Msg: Input String Was Not in a Correct Format
How to Test If Type Is Primitive
Unique File Identifier in Windows
Uploadfile with Post Values by Webclient
Add Search Functionality on Dropdownlistfor
JavaScript Date to C# via Ajax
Is There an Equivalent to the Scanner Class in C# for Strings
Refresh Datagridview When Updating Data Source
How to Implement Url Rewriting Similar to So
Error on If Statement - Cannot Implicitly Convert Type to 'Bool'