Multiple file-extensions searchPattern for System.IO.Directory.GetFiles
C#.Netsystem.io.directoryC# Problem Overview
What is the syntax for setting multiple file-extensions as searchPattern
on Directory.GetFiles()
? For example filtering out files with .aspx and .ascx extensions.
// TODO: Set the string 'searchPattern' to only get files with
// the extension '.aspx' and '.ascx'.
var filteredFiles = Directory.GetFiles(path, searchPattern);
Update: LINQ is not an option, it has to be a searchPattern
passed into GetFiles
, as specified in the question.
C# Solutions
Solution 1 - C#
var filteredFiles = Directory
.GetFiles(path, "*.*")
.Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
.ToList();
Edit 2014-07-23
You can do this in .NET 4.5 for a faster enumeration:
var filteredFiles = Directory
.EnumerateFiles(path) //<--- .NET 4.5
.Where(file => file.ToLower().EndsWith("aspx") || file.ToLower().EndsWith("ascx"))
.ToList();
Solution 2 - C#
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:
> ///
> // 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)); }
Solution 3 - C#
I like this method, because it is readable and avoids multiple iterations of the directory:
var allowedExtensions = new [] {".doc", ".docx", ".pdf", ".ppt", ".pptx", ".xls", ".xslx"};
var files = Directory
.GetFiles(folder)
.Where(file => allowedExtensions.Any(file.ToLower().EndsWith))
.ToList();
Solution 4 - C#
GetFiles can only match a single pattern, but you can use Linq to invoke GetFiles with multiple patterns:
FileInfo[] fi = new string[]{"*.txt","*.doc"}
.SelectMany(i => di.GetFiles(i, SearchOption.AllDirectories))
.ToArray();
See comments section here: http://www.codeproject.com/KB/aspnet/NET_DirectoryInfo.aspx
Solution 5 - C#
var filteredFiles = Directory
.EnumerateFiles(path, "*.*") // .NET4 better than `GetFiles`
.Where(
// ignorecase faster than tolower...
file => file.ToLower().EndsWith("aspx")
|| file.EndsWith("ascx", StringComparison.OrdinalIgnoreCase))
.ToList();
- Don't forget the new .NET4
Directory.EnumerateFiles
for a performance boost (https://stackoverflow.com/questions/5669617/what-is-the-difference-between-directory-enumeratefiles-vs-directory-getfiles) - "IgnoreCase" should be faster than "ToLower"
Or, it may be faster to split and merge your globs (at least it looks cleaner):
"*.ext1;*.ext2".Split(';')
.SelectMany(g => Directory.EnumerateFiles(path, g))
.ToList();
Solution 6 - C#
I fear you will have to do somthing like this, I mutated the regex from here.
var searchPattern = new Regex(
@"$(?<=\.(aspx|ascx))",
RegexOptions.IgnoreCase);
var files = Directory.EnumerateFiles(path)
.Where(f => searchPattern.IsMatch(f))
.ToList();
Solution 7 - C#
The easy-to-remember, lazy and perhaps imperfect solution:
Directory.GetFiles(dir, "*.dll").Union(Directory.GetFiles(dir, "*.exe"))
Solution 8 - C#
I would use the following:
var ext = new string[] { ".ASPX", ".ASCX" };
FileInfo[] collection = (from fi in new DirectoryInfo(path).GetFiles()
where ext.Contains(fi.Extension.ToUpper())
select fi)
.ToArray();
EDIT: corrected due mismatch between Directory and DirectoryInfo
Solution 9 - C#
I would try to specify something like
var searchPattern = "as?x";
it should work.
Solution 10 - C#
A more efficient way of getting files with the extensions ".aspx" and ".ascx" that avoids querying the file system several times and avoids returning a lot of undesired files, is to pre-filter the files by using an approximate search pattern and to refine the result afterwards:
var filteredFiles = Directory.GetFiles(path, "*.as?x")
.Select(f => f.ToLowerInvariant())
.Where(f => f.EndsWith("px") || f.EndsWith("cx"))
.ToList();
Solution 11 - C#
/// <summary>
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// </summary>
/// <param name="srcDirs">The directories to seach</param>
/// <param name="searchPatterns">the list of search patterns</param>
/// <param name="searchOption"></param>
/// <returns>The list of files that match the specified pattern</returns>
public static string[] GetFilesUsingLINQ(string[] srcDirs,
string[] searchPatterns,
SearchOption searchOption = SearchOption.AllDirectories)
{
var r = from dir in srcDirs
from searchPattern in searchPatterns
from f in Directory.GetFiles(dir, searchPattern, searchOption)
select f;
return r.ToArray();
}
Solution 12 - C#
public static bool CheckFiles(string pathA, string pathB)
{
string[] extantionFormat = new string[] { ".war", ".pkg" };
return CheckFiles(pathA, pathB, extantionFormat);
}
public static bool CheckFiles(string pathA, string pathB, string[] extantionFormat)
{
System.IO.DirectoryInfo dir1 = new System.IO.DirectoryInfo(pathA);
System.IO.DirectoryInfo dir2 = new System.IO.DirectoryInfo(pathB);
// Take a snapshot of the file system. list1/2 will contain only WAR or PKG
// files
// fileInfosA will contain all of files under path directories
FileInfo[] fileInfosA = dir1.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
// list will contain all of files that have ..extantion[]
// Run on all extantion in extantion array and compare them by lower case to
// the file item extantion ...
List<System.IO.FileInfo> list1 = (from extItem in extantionFormat
from fileItem in fileInfosA
where extItem.ToLower().Equals
(fileItem.Extension.ToLower())
select fileItem).ToList();
// Take a snapshot of the file system. list1/2 will contain only WAR or
// PKG files
// fileInfosA will contain all of files under path directories
FileInfo[] fileInfosB = dir2.GetFiles("*.*",
System.IO.SearchOption.AllDirectories);
// list will contain all of files that have ..extantion[]
// Run on all extantion in extantion array and compare them by lower case to
// the file item extantion ...
List<System.IO.FileInfo> list2 = (from extItem in extantionFormat
from fileItem in fileInfosB
where extItem.ToLower().Equals
(fileItem.Extension.ToLower())
select fileItem).ToList();
FileCompare myFileCompare = new FileCompare();
// This query determines whether the two folders contain
// identical file lists, based on the custom file comparer
// that is defined in the FileCompare class.
return list1.SequenceEqual(list2, myFileCompare);
}
Solution 13 - C#
Instead of the EndsWith function, I would choose to use the Path.GetExtension()
method instead. Here is the full example:
var filteredFiles = Directory.EnumerateFiles( path )
.Where(
file => Path.GetExtension(file).Equals( ".aspx", StringComparison.OrdinalIgnoreCase ) ||
Path.GetExtension(file).Equals( ".ascx", StringComparison.OrdinalIgnoreCase ) );
or:
var filteredFiles = Directory.EnumerateFiles(path)
.Where(
file => string.Equals( Path.GetExtension(file), ".aspx", StringComparison.OrdinalIgnoreCase ) ||
string.Equals( Path.GetExtension(file), ".ascx", StringComparison.OrdinalIgnoreCase ) );
(Use StringComparison.OrdinalIgnoreCase
if you care about performance: MSDN string comparisons)
Solution 14 - C#
You can do it like this
new DirectoryInfo(path).GetFiles().Where(Current => Regex.IsMatch(Current.Extension, "\\.(aspx|ascx)", RegexOptions.IgnoreCase)
Solution 15 - C#
look like this demo:
void Main()
{
foreach(var f in GetFilesToProcess("c:\\", new[] {".xml", ".txt"}))
Debug.WriteLine(f);
}
private static IEnumerable<string> GetFilesToProcess(string path, IEnumerable<string> extensions)
{
return Directory.GetFiles(path, "*.*")
.Where(f => extensions.Contains(Path.GetExtension(f).ToLower()));
}
Solution 16 - C#
@Daniel B, thanks for the suggestion to write my own version of this function. It has the same behavior as Directory.GetFiles, but supports regex filtering.
string[] FindFiles(FolderBrowserDialog dialog, string pattern)
{
Regex regex = new Regex(pattern);
List<string> files = new List<string>();
var files=Directory.GetFiles(dialog.SelectedPath);
for(int i = 0; i < files.Count(); i++)
{
bool found = regex.IsMatch(files[i]);
if(found)
{
files.Add(files[i]);
}
}
return files.ToArray();
}
I found it useful, so I thought I'd share.
Solution 17 - C#
c# version of @qfactor77's answer. This is the best way without LINQ .
string[] wildcards= {"*.mp4", "*.jpg"};
ReadOnlyCollection<string> filePathCollection = FileSystem.GetFiles(dirPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, wildcards);
string[] filePath=new string[filePathCollection.Count];
filePathCollection.CopyTo(filePath,0);
now return filePath
string array. In the beginning you need
using Microsoft.VisualBasic.FileIO;
using System.Collections.ObjectModel;
also you need to add reference to Microsoft.VisualBasic
Solution 18 - C#
I did a simple way for seach as many extensions as you need, and with no ToLower(), RegEx, foreach...
List<String> myExtensions = new List<String>() { ".aspx", ".ascx", ".cs" }; // You can add as many extensions as you want.
DirectoryInfo myFolder = new DirectoryInfo(@"C:\FolderFoo");
SearchOption option = SearchOption.TopDirectoryOnly; // Use SearchOption.AllDirectories for seach in all subfolders.
List<FileInfo> myFiles = myFolder.EnumerateFiles("*.*", option)
.Where(file => myExtensions
.Any(e => String.Compare(file.Extension, e, CultureInfo.CurrentCulture, CompareOptions.IgnoreCase) == 0))
.ToList();
Working on .Net Standard 2.0.
Solution 19 - C#
var filtered = Directory.GetFiles(path)
.Where(file => file.EndsWith("aspx", StringComparison.InvariantCultureIgnoreCase) || file.EndsWith("ascx", StringComparison.InvariantCultureIgnoreCase))
.ToList();
Solution 20 - C#
Just would like to say that if you use FileIO.FileSystem.GetFiles
instead of Directory.GetFiles
, it will allow an array of wildcards.
For example:
Dim wildcards As String() = {"*.html", "*.zip"}
Dim ListFiles As List(Of String) = FileIO.FileSystem.GetFiles(directoryyouneed, FileIO.SearchOption.SearchTopLevelOnly, wildcards).ToList
Solution 21 - C#
(Sorry to write this as an answer, but I don't have privileges to write comments yet.)
Note that the FileIO.FileSystem.GetFiles() method from Microsoft.VisualBasic is just a wrapper to execute a search for each provided pattern and merge the results. When checking the source from the .pbd file, you can see from this fragment FileSystem.FindPaths is executed for each pattern in the collection:
private static void FindFilesOrDirectories(
FileSystem.FileOrDirectory FileOrDirectory,
string directory,
SearchOption searchType,
string[] wildcards,
Collection<string> Results)
{
// (...)
string[] strArray = wildcards;
int index = 0;
while (index < strArray.Length)
{
string wildCard = strArray[index];
FileSystem.AddToStringCollection(Results, FileSystem.FindPaths(FileOrDirectory, directory, wildCard));
checked { ++index; }
}
// (...)
}