1

Directory.GetFiles 中传入搜索字符串(Search Pattern)的神奇规则

 1 year ago
source link: http://blog.walterlv.com/post/search-pattern-of-dotnet-directory-getfiles
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
吕毅 发表于 9 小时前

众所周知,文件名的匹配规则里同配符 ? 代表单个字符,通配符 * 代表多个字符。然而,具体到 Directory.GetFiles(string path, string searchPattern) 方法调用时,却又有一些大家不一定知道的细节。不信?我出一道题大家试试!


一道测试题

假设在调用 Directory.GetFiles(string path, string searchPattern) 时,searchPattern 传入下表左侧的字符串;请在同一行的两个文件里,能匹配上的打个勾,不能匹配的打个叉。

搜索字符串文件 1文件 2
*.xlsbook.xlsbool.xlsx
*.aifile.aifile.aif
file?.txtfile1.txtfile1.txtother
file*.txtfile1.txtfile1.txtother
*1*.txtfile1.txtthisisastrangefile.txt

5 秒后给出答案。

匹配字符串文件 1文件 2
1*.xls✔️ book.xls✔️ bool.xlsx
2*.ai✔️ file.ai❌ file.aif
3file?.txt✔️ file1.txt❌ file1.txtother
4file*.txt✔️ file1.txt✔️ file1.txtother
5*1*.txt✔️ file1.txt✔️ thisisastrangefile.txt

如果你觉得奇怪,那就不奇怪了。因为这 5 个搜索案例均来自于微软官方文档,而微软花了很大篇幅来解释为什么是这样的行为。

第 1、2 行,不一样的地方是扩展名长度。

  • 如果搜索字符串扩展名长度为 3,那么文件名里扩展名前 3 位为此扩展名的文件都将匹配上
  • 如果搜索字符串扩展名长度不是 3,那么扩展名必须严格匹配

第 3、4 行,不一样 的地方是 ?*

  • 如果使用 ? 匹配文件,那么文件扩展名必须完全相同才能匹配上
  • 如果使用 * 匹配文件,那么文件扩展名以此开头的都能匹配上

第 5 行,为什么明明文件名里没有 1 却也能匹配上呢?

这需要简单说一下 8.3 文件名。

8.3文件名一种文件名规范,它主要运用于FAT文件系统中。其后继者NTFS文件系统也支持8.3文件名。这种规范之所以被称为“8.3”,是因为其文件名的特殊格式:文件名的主体部分最多只能包含8个字符,而文件扩展名最多只能包含3个字符。二者之间用“.”相连。8.3文件名的目录和文件名都仅使用大写字母,但DOS和命令提示符都不大小写敏感(当然,如果使用UNIX或类Unix等一般大小写敏感的操作系统,则应注意)。

8.3文件名必须包含主体文件名,但不必须包含扩展名,二者之间用“.”相连。但是如果输入“.”后没有输入扩展名,则“.”没有意义,会被忽略。比如12345678.会被系统保存为12345678。

为了兼容老程序,Windows 会有一个算法让 8.3 文件名与长文件名对应,具体对应方法可以参考维基百科:8.3文件名 - 维基百科,自由的百科全书

前面的“thisisastrangefile.txt”对应的 8.3 文件名为“THISIS~1.TXT”,而 Directory.GetFiles 会同时匹配长文件名和 8.3 文件名,所以,“thisisastrangefile.txt”就神奇般地被匹配上了。

以下是实测结果。图片的上方是我创建的被测文件名,下方是调用 Directory.GetFiles 来验证搜索结果。

实测结果

需要注意的是,这个匹配规则只适用于 Windows 下的 API 调用,不适用于用户在文件资源管理器中的搜索操作。搜索操作里没有这么奇怪的规则,单单就是字符串包含以及通配符而已。


参考资料

本文会经常更新,请阅读原文: https://blog.walterlv.com/post/search-pattern-of-dotnet-directory-getfiles ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 吕毅 (包含链接: https://blog.walterlv.com ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 ([email protected])


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK