你可以调用Directory.GetFiles()与多个filter?

我正在尝试使用Directory.GetFiles()方法来检索多种types的文件,如mp3jpg的列表。 我已经尝试了以下两个没有运气:

 Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories); Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories); 

有一个方法可以在一个电话中做到这一点?

对于.NET 4.0及更高版本,

 var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories) .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg")); 

对于早期版本的.NET,

 var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories) .Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg")); 

编辑: 请阅读评论。 Paul Farry提出的改进以及Christian.K指出的记忆/performance问题都非常重要。

这个怎么样:

 private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption) { return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray(); } 

我在这里find它(在评论中): http : //msdn.microsoft.com/en-us/library/wz42302f.aspx

如果你有一个扩展名列表检查你可以使用以下。 我不想创build大量的OR语句,所以我修改了lette写的东西。

 string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08"; foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower()))) { //do work here } 

对于

 var exts = new[] { "mp3", "jpg" }; 

你可以:

 public IEnumerable<string> FilterFiles(string path, params string[] exts) { return Directory .EnumerateFiles(path, "*.*") .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase))); } 
  • 不要忘了新的.NET4 Directory.EnumerateFiles性能提升( Directory.EnumerateFiles与Directory.GetFiles有什么区别? )
  • “IgnoreCase”应该快于“ToLower”( .ToLower().EndsWith("aspx") .EndsWith("aspx", StringComparison.OrdinalIgnoreCase)而不是.ToLower().EndsWith("aspx")

但是,当你分离filter并合并结果时, EnumerateFiles的真正好处就EnumerateFiles出来了:

 public IEnumerable<string> FilterFiles(string path, params string[] exts) { return exts.Select(x => "*." + x) // turn into globs .SelectMany(x => Directory.EnumerateFiles(path, x) ); } 

如果你不必把它们变成球体(即exts = new[] {"*.mp3", "*.jpg"}exts = new[] {"*.mp3", "*.jpg"}它会变得更快一些。

基于以下LinqPadtesting的性能评估(注: Perf只是重复代表10000次) https://gist.github.com/zaus/7454021

(从“重复”重新发布和扩展,因为该问题明确要求没有LINQ: 多个文件扩展名为System.IO.Directory.GetFiles searchPattern )

我知道这是老问题,但LINQ:(.NET40 +)

 var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, @"^.+\.(wav|mp3|txt)$")); 

另一种使用Linq的方式,但不必返回所有内容并在内存中进行过滤。

 var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories)); 

它实际上是对GetFiles() 2次调用,但我认为它符合问题的精神,并将它们返回到一个枚举中。

不。 尝试以下操作:

 List<string> _searchPatternList = new List<string>(); ... List<string> fileList = new List<string>(); foreach ( string ext in _searchPatternList ) { foreach ( string subFile in Directory.GetFiles( folderName, ext ) { fileList.Add( subFile ); } } // Sort alpabetically fileList.Sort(); // Add files to the file browser control foreach ( string fileName in fileList ) { ...; } 

取自: http : //blogs.msdn.com/markda/archive/2006/04/20/580075.aspx

 var set = new HashSet<string> { ".mp3", ".jpg" }; 

然后

 Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) .Where(f => set.Contains( new FileInfo(f).Extension, StringComparer.OrdinalIgnoreCase)); 

要么

 from file in Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) from ext in set where String.Equals(ext, new FileInfo(file).Extension, StringComparison.OrdinalIgnoreCase) select file; 

我无法使用.Where方法,因为我在.NET Framework 2.0中进行编程(Linq仅在.NET Framework 3.5+中受支持)。

下面的代码不区分大小写(所以.CaB.cab也会列出)。

 string[] ext = new string[2] { "*.CAB", "*.MSU" }; foreach (string found in ext) { string[] extracted = Directory.GetFiles("C:\\test", found, System.IO.SearchOption.AllDirectories); foreach (string file in extracted) { Console.WriteLine(file); } } 

还有一个下降的解决scheme,似乎没有任何内存或性能开销,并相当优雅:

 string[] filters = new[]{"*.jpg", "*.png", "*.gif"}; string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray(); 

下面的函数search多个模式,用逗号分隔。 您也可以指定排除,例如:“!web.config”将search所有文件并排除“web.config”。 模式可以混合使用。

 private string[] FindFiles(string directory, string filters, SearchOption searchOption) { if (!Directory.Exists(directory)) return new string[] { }; var include = (from filter in filters.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim()); var exclude = (from filter in include where filter.Contains(@"!") select filter); include = include.Except(exclude); if (include.Count() == 0) include = new string[] { "*" }; var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", @"\.").Replace("*", ".*").Replace("?", ".")); Regex regex = new Regex(string.Join("|", rxfilters.ToArray())); List<Thread> workers = new List<Thread>(); List<string> files = new List<string>(); foreach (string filter in include) { Thread worker = new Thread( new ThreadStart( delegate { string[] allfiles = Directory.GetFiles(directory, filter, searchOption); if (exclude.Count() > 0) { lock (files) files.AddRange(allfiles.Where(p => !regex.Match(p).Success)); } else { lock (files) files.AddRange(allfiles); } } )); workers.Add(worker); worker.Start(); } foreach (Thread worker in workers) { worker.Join(); } return files.ToArray(); } 

用法:

 foreach (string file in FindFiles(@"D:\628.2.11", @"!*.config, !*.js", SearchOption.AllDirectories)) { Console.WriteLine(file); } 

只是find了另一种方式来做到这一点。 仍然不是一个行动,但抛出去看看别人的想法。

 private void getFiles(string path) { foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch)) { Debug.Print(s); } } private bool predicate_FileMatch(string fileName) { if (fileName.EndsWith(".mp3")) return true; if (fileName.EndsWith(".jpg")) return true; return false; } 
 List<string> FileList = new List<string>(); DirectoryInfo di = new DirectoryInfo("C:\\DirName"); IEnumerable<FileInfo> fileList = di.GetFiles("*.*"); //Create the query IEnumerable<FileInfo> fileQuery = from file in fileList where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png") orderby file.LastWriteTime select file; foreach (System.IO.FileInfo fi in fileQuery) { fi.Attributes = FileAttributes.Normal; FileList.Add(fi.FullName); } 

制作你想要的一个string即“.mp3.jpg.wma.wmf”的扩展名,然后检查每个文件是否包含你想要的扩展名。 这适用于.net 2.0,因为它不使用LINQ。

 string myExtensions=".jpg.mp3"; string[] files=System.IO.Directory.GetFiles("C:\myfolder"); foreach(string file in files) { if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower())) { //this file has passed, do something with this file } } 

这种方法的优点是你可以添加或删除扩展名,而不需要编辑代码,即添加PNG图像,只需写myExtensions =“。jpg.mp3.png”。

 /// <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(); } 

Nop …我相信你必须拨打和你想要的文件types一样多的电话。

我会自己创build一个函数,我需要的string与我需要的扩展,然后迭代该数组进行所有必要的调用。 该函数将返回与我发送的扩展匹配的文件的通用列表。

希望它有帮助。

在.NET 2.0中(没有Linq):

 public static List<string> GetFilez(string path, System.IO.SearchOption opt, params string[] patterns) { List<string> filez = new List<string>(); foreach (string pattern in patterns) { filez.AddRange( System.IO.Directory.GetFiles(path, pattern, opt) ); } // filez.Sort(); // Optional return filez; // Optional: .ToArray() } 

然后使用它:

 foreach (string fn in GetFilez(path , System.IO.SearchOption.AllDirectories , "*.xml", "*.xml.rels", "*.rels")) {} 
 DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/")); //Using Union FileInfo[] files = directory.GetFiles("*.xlsx") .Union(directory .GetFiles("*.csv")) .ToArray(); 

关于什么

 string[] filesPNG = Directory.GetFiles(path, "*.png"); string[] filesJPG = Directory.GetFiles(path, "*.jpg"); string[] filesJPEG = Directory.GetFiles(path, "*.jpeg"); int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length; List<string> filesAll = new List<string>(totalArraySizeAll); filesAll.AddRange(filesPNG); filesAll.AddRange(filesJPG); filesAll.AddRange(filesJPEG); 

我有同样的问题,找不到正确的解决scheme,所以我写了一个名为GetFiles的函数:

 /// <summary> /// Get all files with a specific extension /// </summary> /// <param name="extensionsToCompare">string list of all the extensions</param> /// <param name="Location">string of the location</param> /// <returns>array of all the files with the specific extensions</returns> public string[] GetFiles(List<string> extensionsToCompare, string Location) { List<string> files = new List<string>(); foreach (string file in Directory.GetFiles(Location)) { if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.')+1).ToLower())) files.Add(file); } files.Sort(); return files.ToArray(); } 

这个函数只会调用Directory.Getfiles()一次。

例如调用这样的函数:

 string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder"); 

编辑:要获得多个扩展名的一个文件使用这一个:

 /// <summary> /// Get the file with a specific name and extension /// </summary> /// <param name="filename">the name of the file to find</param> /// <param name="extensionsToCompare">string list of all the extensions</param> /// <param name="Location">string of the location</param> /// <returns>file with the requested filename</returns> public string GetFile( string filename, List<string> extensionsToCompare, string Location) { foreach (string file in Directory.GetFiles(Location)) { if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf('.') - (Location.Length + 1))).ToLower() == filename) return file; } return ""; } 

例如调用这样的函数:

 string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder"); 

我想知道为什么有这么多的“解决scheme”张贴?

如果我的新手理解GetFiles的工作方式是正确的,那么只有两个选项,上面的任何解决scheme都可以归结为这些:

  1. GetFiles,然后过滤:快速,但由于存储开销,直到应用filter的内存杀手

  2. GetFiles过滤:设置的filter越多,但内存使用率低,因为没有存储开销。
    这在上面的post中有一个令人印象深刻的基准testing:每个filter选项都会导致一个单独的GetFile操作,所以硬盘的同一部分会被读取几次。

在我看来,选项1)更好,但是像C:\这样的文件夹上使用SearchOption.AllDirectories会使用大量的内存。
因此,我只是做一个recursion子方法,通过所有子文件夹使用选项1)

这应该会导致每个文件夹上只有一个GetFiles操作,因此速度很快(选项1),但是在每个子文件夹的读取 – >开销被删除后,每个子文件夹被删除后,仅使用less量的内存。

如果我错了,请纠正我。 我正如我所说的相当新的编程,但要深入了解的东西,最终成为在这:)

或者,您可以将扩展string转换为String ^

 vector <string> extensions = { "*.mp4", "*.avi", "*.flv" }; for (int i = 0; i < extensions.size(); ++i) { String^ ext = gcnew String(extensions[i].c_str());; String^ path = "C:\\Users\\Eric\\Videos"; array<String^>^files = Directory::GetFiles(path,ext); Console::WriteLine(ext); cout << " " << (files->Length) << endl; } 

我不知道什么解决scheme更好,但我使用这个:

 String[] ext = "*.ext1|*.ext2".Split('|'); List<String> files = new List<String>(); foreach (String tmp in ext) { files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories)); }