列出与模式匹配的文件夹中的文件

时间:2014-09-09 08:19:08

标签: c# .net directory

我需要在目录中列出与某些模式匹配的文件。 我试过玩Directory.GetFiles,但不完全 得到它为什么以某种方式表现。

1)例如,这段代码:

            string[] dirs = Directory.GetFiles(@"c:\test\", "*t");

            foreach (string dir in dirs)
            {
                Debugger.Log(0, "", dir);
                Debugger.Log(0, "", "\n");

            }

输出:

c:\test\11.11.2007.txtGif
c:\test\12.1.1990.txt
c:\test\2.tGift
c:\test\2.txtGif
c:\test\test.txt
...others hidden

您可以看到一些文件以f结尾,但仍然通过查询返回,为什么

2)另外,这个:

                string[] dirs = Directory.GetFiles(@"c:\test\", "*.*.*.txt");


                foreach (string dir in dirs)
                {
                    Debugger.Log(0, "", dir);
                    Debugger.Log(0, "", "\n");

                }

返回:

c:\test\1.1.1990.txt
c:\test\1.31.1990.txt
c:\test\12.1.1990.txt
c:\test\12.31.1990.txt

根据文档http://msdn.microsoft.com/en-us/library/07wt70x2(v=vs.110).aspx)我认为它也必须返回 这个文件在目录中:

11.11.2007.txtGif

,因为扩展程序(在查询字符串中)长度为3个字母, 但它没有。为什么? (当查询扩展名为3个字母时,doc说它将返回以指定扩展名开头的扩展名,例如,请参阅备注)。


我是唯一一个发现这些结果奇怪的人吗?

如果想要列出符合特定模式的文件夹中的文件,是否还有其他方法可供使用?

在我的情况下,用户可以随意输入一些模式,我不想依赖 我不确定结果的方法(就像GetFiles一样)。

3 个答案:

答案 0 :(得分:4)

这是Windows API的工作方式 - 如果在命令提示符中使用dir命令,您将看到相同的结果。这不使用正则表达式!它很晦涩......

如果您想进行自己的过滤,可以这样做:

var filesEndingInT = Directory.EnumerateFiles(@"c:\test\").Where(f => f.EndsWith("t"));

如果你想使用正则表达式进行匹配,你可以这样做:

Regex regex = new Regex(".*t$");
var matches = Directory.EnumerateFiles(@"c:\test\").Where(f => regex.IsMatch(f));

我怀疑你会想让用户输入简化的模式形式并将其变成正则表达式,例如。

"*.t" -> ".*t$"

查找以t结尾的所有文件名的正则表达式是"。* t $":

.*t$

Regular expression visualization

Debuggex Demo

答案 1 :(得分:4)

所有这些行为与您链接的文档中描述的完全相同。这是相关部分的摘录:

  

在searchPattern中使用星号通配符时   as" * .txt",指定扩展名中的字符数   影响搜索如下:

     
      
  • 如果指定的扩展名长度恰好为三个字符,则该方法返回扩展名以指定开头的文件   延期。例如," * .xls"返回" book.xls"和   " book.xlsx"

  •   
  • 在所有其他情况下,该方法返回与指定扩展名完全匹配的文件。例如," * .ai"返回" file.ai"但不是   " file.aif"

  •   
     

使用问号通配符时,此方法返回   仅限与指定文件扩展名匹配的文件。例如,给定   两个文件," file1.txt"和" file1.txtother",在目录中搜索   "文件的模式?.txt"只返回第一个文件,而返回搜索   模式"文件* .txt"返回两个文件。 NoteNote

     

因为此方法使用8.3文件检查文件名   名称格式和长文件名格式,类似的搜索模式   " 1 .TXT"可能会返回意外的文件名。例如,使用   搜索模式" 1 .txt"返回" longfilename.txt"因为   等效的8.3文件名格式是" LONGFI~1.TXT"。

http://msdn.microsoft.com/en-us/library/wz42302f%28v=vs.110%29.aspx

上面的最后一段清楚地解释了搜索*t时的搜索结果。您可以使用命令dir C:\test /x来显示8.3文件名。在此处,C:\test\11.11.2007.txtGif*t匹配,因为其8.3文件名为111120~1.TXT

对于*.*.*.txt的处理,我认为您要么错误地解释了关于三个字母的文件扩展名的第一位,要么可能写得不是很清楚。请注意,他们在searchPattern中特别提到了通配符用法,例如" * .txt"'。您的搜索模式与之匹配,因此您必须在这些行之间进行一些阅读,以了解为什么他们对三个字母文件扩展名的评论适用于他们给出的示例而不是您的示例。真的,我认为如果你只考虑8.3文件名的最后一点,可以忽略整个顶部。在通配符之后处理三个字母的文件扩展名实际上只是8.3文件名搜索行为的副作用。

考虑他们给出的例子:

  

" *。XLS"返回" book.xls"和" book.xlsx"

这是因为" book.xls"的文件名。 (8.3和长文件名,因为名称自然符合8.3)" book.xlsx"的8.3文件名(" BOOK~1.XLS")匹配" *。xls"的查询。

  

" * AI"返回" file.ai"但不是" file.aif"

这是因为" file.ai"自然匹配" * .ai"而" file.aif"没有按'吨。 8.3搜索行为根本没有在这里发挥作用,因为两个文件名都已经符合8.3。但是,即使它们不是,也是如此,因为对于扩展名为" .ai"的文件的任何8.3文件名都是如此。只是" .AI"。

唯一的原因是,搜索中的文件扩展名是否正好是三个字符是因为8.3文件名包含在搜索中, 8.3 filname扩展名用于具有长文件名的对象将始终只有长文件名中最后一个点后面的前三个字符。上面文档中缺少的关键部分是"前三个字符"匹配仅针对8.3文件名 完成。

所以,让我们来看看你在这里提出的异常情况。 (如果您想要解释除*.t*.*.*.txt的结果之外的任何其他奇怪行为,请将它们作为单独的问题发布。)


TL; DR:

搜索*t的输出包括11.11.2007.txtGif2.txtGif

这是因为8.3文件名匹配*t

的模式

11.11.2007.txtGif = 111120~1.TXT 2.txtGIF = 2BEFD~1.TXT

(两个8.3文件名都以" T"。)

结尾

搜索*.*.*.txt的输出不包括11.11.2007.txtGif

这是因为长文件名和8.3文件名都不匹配*.*.*.txt的模式。

11.11.2007.txtGif = 111120~1.TXT

(长文件名不匹配,因为它不会以" .txt"结尾,并且8.3文件名不匹配,因为它只有一个点。)

答案 2 :(得分:0)

https://docs.microsoft.com/en-us/dotnet/api/system.io.directoryinfo.getfiles?view=netframework-4.5

上面的Microsoft文档照常是错误的, 它说这段代码:

            DirectoryInfo di = new DirectoryInfo(@"C:\Users\tomfitz\Documents\ExampleDir");
            Console.WriteLine("No search pattern returns:");

            Console.WriteLine();

            Console.WriteLine("Search pattern *2* returns:");
            foreach (var fi in di.GetFiles("*2*"))
            {
                Console.WriteLine(fi.Name);
                Console.WriteLine(fi.Fullname); // this reveals the bug
            }

应返回以下,但不会

它仍然与整个文件 path 匹配,而不仅仅是文件名。

Search pattern *2* returns:
log2.txt
test2.txt