Can you call Directory.GetFiles() with multiple fi

2018-12-31 06:58发布

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("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);

Is there a way to do this in one call?

26条回答
与君花间醉酒
2楼-- · 2018-12-31 07:41

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

Code below is not case sensitive (so .CaB or .cab will be listed too).

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);
    }
}
查看更多
何处买醉
3楼-- · 2018-12-31 07:41

I wonder why there are so many "solutions" posted?

If my rookie-understanding on how GetFiles works is right, there are only two options and any of the solutions above can be brought down to these:

  1. GetFiles, then filter: Fast, but a memory killer due to storing overhead untill the filters are applied

  2. Filter while GetFiles: Slower the more filters are set, but low memory usage as no overhead is stored.
    This is explained in one of the above posts with an impressive benchmark: Each filter option causes a seperate GetFile-operation so the same part of the harddrive gets read several times.

In my opinion Option 1) is better, but using the SearchOption.AllDirectories on folders like C:\ would use huge amounts of memory.
Therefor i would just make a recursive sub-method that goes through all subfolders using option 1)

This should cause only 1 GetFiles-operation on each folder and therefor be fast (Option 1), but use only a small amount of memory as the filters are applied afters each subfolders' reading -> overhead is deleted after each subfolder.

Please correct me if I am wrong. I am as i said quite new to programming but want to gain deeper understanding of things to eventually become good at this :)

查看更多
墨雨无痕
4楼-- · 2018-12-31 07:46

Using GetFiles search pattern for filtering the extension is not safe!! For instance you have two file Test1.xls and Test2.xlsx and you want to filter out xls file using search pattern *.xls, but GetFiles return both Test1.xls and Test2.xlsx I was not aware of this and got error in production environment when some temporary files suddenly was handled as right files. Search pattern was *.txt and temp files was named *.txt20181028_100753898 So search pattern can not be trusted, you have to add extra check on filenames as well.

查看更多
春风洒进眼中
5楼-- · 2018-12-31 07:47

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.

查看更多
笑指拈花
6楼-- · 2018-12-31 07:53

How about this:

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

I found it here (in the comments): http://msdn.microsoft.com/en-us/library/wz42302f.aspx

查看更多
忆尘夕之涩
7楼-- · 2018-12-31 07:53
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);
}
查看更多
登录 后发表回答