你可以使用多个过滤器调用Directory.GetFiles()吗?

Jas*_*n Z 338 .net c# filesystems

我正在尝试使用该Directory.GetFiles()方法来检索多种类型的文件列表,例如mp3's和jpg's.我试过以下两个都没有运气:

Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
Run Code Online (Sandbox Code Playgroud)

有没有办法在一个电话中执行此操作?

Chr*_*tte 493

对于.NET 4.0及更高版本,

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

对于早期版本的.NET,

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

编辑: 请阅读评论.Paul Farry建议的改进以及Christian.K指出的内存/性能问题都非常重要.

  • 请注意,使用.NET 4.0,您可以将`Directory.GetFiles`替换为`Directory.EnumerateFiles`,http://msdn.microsoft.com/en-us/library/dd383571.aspx,这将避免@的内存问题Christian.K提到. (111认同)
  • 你可以使用`s.EndsWith(".mp3",StringComparison.OrdinalIgnoreCase) (97认同)
  • 请确保您理解其含义:这将返回字符串数组中的*all*文件,然后通过您指定的扩展名对其进行过滤.如果"C:\ Path"下面没有很多文件,那可能不是一个大问题,但可能是"C:\"之类的内存/性能问题. (53认同)
  • ... ... 2年后:好的代码,但请注意这一点,如果你有一个以.JPG结尾的文件,它将无法实现.最好添加`s.ToLower().Endswith ...` (22认同)
  • 伙计,我必须更频繁地考虑LINQ.好的解决方案 (10认同)
  • 如果您想在有许多可能的扩展的情况下进一步提高性能,最好创建一个包含所有扩展的 HashSet 并执行 `Where(f => _validExtensions.Contains(Path.GetExtension(f).ToLower()))`。基本上,`Contains` 比多次执行字符串比较要快得多。 (4认同)
  • 我做了一些性能改进,并在下面的答案中提供了比较代码:http://stackoverflow.com/questions/163162/can-you-call-directory-getfiles-with-multiple-filters/19961761#19961761 (2认同)

Alb*_*ert 58

这个怎么样:

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();
}
Run Code Online (Sandbox Code Playgroud)

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

  • @DanW评分最高的答案肯定会给记忆带来负担,但我认为这不应该是一个问题.我也喜欢这个答案,但它实际上(比)接受的答案要慢得多.检查一下[SpeedTest](http://www.justmygame.net/wps/multiple-extensions/) (11认同)
  • 如果只有两个扩展,它只有两倍的速度.如果你有一个X扩展列表,那么它将是X倍慢.因为在这里你多次调用函数Directory.GetFiles,而在另一个解决方案中它只被调用一次. (7认同)

jno*_*iga 32

如果要检查大量扩展名,可以使用以下内容.我不想创建很多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
}
Run Code Online (Sandbox Code Playgroud)

  • System.IO.Path.GetFileName(imageFile) (2认同)
  • 仅供参考:您需要使用System.Linq作为.where( (2认同)
  • 有一个潜在的缺陷。我们早已过去了要求扩展名恰好是三个字符的时代。假设您可能遇到带有“.abc”的文件,并且supportedExtensions包含“.abcd”。会匹配,但不应该匹配。要修复:`supportedExtensions = ".jpg|.abcd|";` 和 `.Contains(Path.GetExtension(s).ToLower() + "|")`。也就是说,在测试中包含您的分隔符。重要提示:您的分隔符还必须位于supportedExceptions 中的最后一个条目之后。 (2认同)

drz*_*aus 29

对于

var exts = new[] { "mp3", "jpg" };
Run Code Online (Sandbox Code Playgroud)

你可以:

public IEnumerable<string> FilterFiles(string path, params string[] exts) {
    return
        Directory
        .EnumerateFiles(path, "*.*")
        .Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
Run Code Online (Sandbox Code Playgroud)

但是,EnumerateFiles当您拆分过滤器并合并结果时,会显示真正的好处:

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

如果你不必将它们变成globs(即exts = new[] {"*.mp3", "*.jpg"}已经),它会变得更快.

基于以下LinqPad测试的性能评估(注意:Perf只重复代理10000次) https://gist.github.com/zaus/7454021

(转发并从'复制'扩展,因为该问题特别请求没有LINQ:System.IO.Directory.GetFiles的多个文件扩展名searchPattern)


小智 16

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

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

  • 好主意。考虑使用`file.ToLower()`来轻松匹配大写扩展名。而且为什么不首先提取扩展名,所以Regex不必检查整个路径:`Regex.IsMatch(Path.GetExtension(file).ToLower(),@“ \。(wav | mp3 | txt)”);` (3认同)

Dav*_*ael 11

另一种使用Linq的方法,但无需返回所有内容并在内存中过滤掉.

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

它实际上是2个调用GetFiles(),但我认为它与问题的精神一致,并将它们归还给一个可枚举的.


小智 11

还有一个下降解决方案似乎没有任何内存或性能开销,并且非常优雅:

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


Not*_*tMe 7

不.请尝试以下方法:

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 )
    {
        ...;
    }
Run Code Online (Sandbox Code Playgroud)

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


aba*_*hev 6

var set = new HashSet<string> { ".mp3", ".jpg" };
Run Code Online (Sandbox Code Playgroud)

然后

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

要么

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


小智 5

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);
}
Run Code Online (Sandbox Code Playgroud)


jay*_*red 5

我不能使用.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);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));

//Using Union

FileInfo[] files = directory.GetFiles("*.xlsx")
                            .Union(directory
                            .GetFiles("*.csv"))
                            .ToArray();
Run Code Online (Sandbox Code Playgroud)


Ste*_*ger 5

在 .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()
}
Run Code Online (Sandbox Code Playgroud)

然后使用它:

foreach (string fn in GetFilez(path
                             , System.IO.SearchOption.AllDirectories
                             , "*.xml", "*.xml.rels", "*.rels"))
{}
Run Code Online (Sandbox Code Playgroud)


Cru*_*ool 5

如果您使用 VB.NET(或将依赖项导入到 C# 项目中),实际上存在一种方便的方法,可以过滤多个扩展:

Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});
Run Code Online (Sandbox Code Playgroud)

在 VB.NET 中,可以通过 My-namespace 访问它:

My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})
Run Code Online (Sandbox Code Playgroud)

不幸的是,这些方便的方法不支持像这样的延迟评估变体Directory.EnumerateFiles()