在 C# 中使用通配符查找文件

Find files using wild card in C#

我正在尝试从目录中查找文件:

String[] search1 = Directory.GetFiles(voiceSource, "85267-*.wav")
                                 .Select(path => Path.GetFileName(path))
                                 .ToArray();

String[] search2 = Directory.GetFiles(voiceSource, "85267 *.wav")
                                 .Select(path => Path.GetFileName(path))
                                 .ToArray();

但在 search1 中,它同时选择了 85267-s.wav85267 -s.wav。但我只想选择 85267-s.wav

search2 表现不错。

我该怎么做?

是的,这是 MS-Dos 8.3 短名称支持的副作用,目前在大多数文件系统上仍处于打开状态。您可以使用 DIR /X 命令看到的东西,它显示那些短名称。在我的机器上:

C:\temp>dir /x *.wav

01/21/2015  09:11 AM                 6 85267-~1.WAV 85267 -s.wav
01/21/2015  09:11 AM                 6              85267-s.wav
               2 File(s)             12 bytes
               0 Dir(s)  235,121,160,192 bytes free

请注意“85267 -s”的简称是如何缺少 space 的。它不是短名称中的有效字符。现在剩下的也符合你的通配符。

那些短名称的麻烦还不止于此,像 *.wav 这样的通配符也会匹配像 foobar.wavx 这样完全不同的文件类型的文件。

坦率地说,短名称生成是上个世纪的遗留物,今天应该关闭。但这通常不是您可以控制的。您必须处理这些意外匹配并仔细检查您返回的内容。以正则表达式为例。

您遇到的问题是由于短文件名。由于 85267 -s.wav 会得到 85267-~1.WAV 并且因为它与通配符 "85267-*.wav" 匹配,所以您可以取回两个文件。

Directory.GetFiles Method (String, String)

中有解释

Because this method checks against file names with both the 8.3 file name format and the long file name format, a search pattern similar to "1.txt" may return unexpected file names. For example, using a search pattern of "1.txt" will return "longfilename.txt" because the equivalent 8.3 file name format would be "longf~1.txt".

对于解决方法,您可以使用 Directory.EnumerateFiles 首先 select 两个符合您条件的文件,然后比较 实际(长) 文件名部分使用 StartsWith。请记住 EnumerateFiles 进行惰性评估。

String[] search1 = Directory.EnumerateFiles(@"C:\test", "85267-*.wav")
                         .Where(file => Path.GetFileName(file).StartsWith("85267-"))
                         .Select(path => Path.GetFileName(path))
                         .ToArray();