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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/163162/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 16:19:54  来源:igfitidea点击:

Can you call Directory.GetFiles() with multiple filters?

c#filesystems.net

提问by Jason Z

I am trying to use the Directory.GetFiles()method to retrieve a list of files of multiple types, such as mp3's and jpg's. I have tried both of the following with no luck:

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

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

Is there a way to do this in one call?

有没有办法在一次通话中做到这一点?

采纳答案by Christoffer Lette

For .NET 4.0 and later,

对于 .NET 4.0 及更高版本,

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

For earlier versions of .NET,

对于 .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 Farrysuggests, and the memory/performance issue that Christian.Kpoints out are both very important.

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

回答by NotMe

Nope. Try the following:

不。请尝试以下操作:

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 )
    {
        ...;
    }

Taken from: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx

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

回答by sebagomez

Nop... I believe you have to make as many calls as the file types you want.

不...我相信你必须根据你想要的文件类型进行尽可能多的调用。

I would create a function myself taking an array on strings with the extensions I need and then iterate on that array making all the necessary calls. That function would return a generic list of the files matching the extensions I'd sent.

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

Hope it helps.

希望能帮助到你。

回答by Jason Z

Just found an another way to do it. Still not one operation, but throwing it out to see what other people think about it.

刚刚找到了另一种方法来做到这一点。仍然不是一个操作,而是把它扔出去看看其他人是怎么想的。

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;
}

回答by Alexander Popov

The following function searches on multiple patterns, separated by commas. You can also specify an exclusion, eg: "!web.config" will search for all files and exclude "web.config". Patterns can be mixed.

以下函数搜索多个模式,以逗号分隔。您还可以指定排除项,例如:“!web.config”将搜索所有文件并排除“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();

}

Usage:

用法:

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

回答by abatishchev

Let

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

Then

然后

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

or

或者

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

回答by Rajeesh Kuthuparakkal

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

回答by jnoreiga

If you have a large list of extensions to check you can use the following. I didn't want to create a lot of OR statements so i modified what lette wrote.

如果您有大量要检查的扩展名列表,您可以使用以下方法。我不想创建很多 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
}

回答by jaysponsored

I can't use .Wheremethod because I'm programming in .NET Framework 2.0 (Linq is only supported in .NET Framework 3.5+).

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

Code below is not case sensitive (so .CaBor .cabwill be listed too).

下面的代码不区分大小写(因此.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);
    }
}

回答by Dave Rael

Another way to use Linq, but without having to return everything and filter on that in memory.

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

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

It's actually 2 calls to GetFiles(), but I think it's consistent with the spirit of the question and returns them in one enumerable.

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