.NET 中的文件通配
在本文中,了解如何将文件通配与 Microsoft.Extensions.FileSystemGlobbing
NuGet 包一起使用。 glob 是一种术语,用于定义基于通配符匹配文件名和目录名的模式。 通配是定义一个或多个 glob 模式,并从包含或排除的匹配项中生成文件的操作。
模式
若要基于用户定义的模式匹配文件系统中的文件,请通过实例化 Matcher 对象开始。 Matcher
可在没有参数的情况下进行实例化,也可以使用 System.StringComparison 参数进行实例化,该参数在内部用于比较模式和文件名。 Matcher
公开以下附加方法:
AddExclude
和 AddInclude
方法都可以调用任意多次,以添加各种要从结果中排除或包含文件名模式。 在实例化了 Matcher
并添加了模式后,它用于通过 Matcher.Execute 方法从起始目录评估匹配项。
扩展方法
Matcher
对象具有多个扩展方法。
多个排除项
若要添加多个排除模式,可使用:
Matcher matcher = new();
matcher.AddExclude("*.txt");
matcher.AddExclude("*.asciidoc");
matcher.AddExclude("*.md");
或者,可使用 MatcherExtensions.AddExcludePatterns(Matcher, IEnumerable<String>[]) 在单个调用中添加多个排除模式:
Matcher matcher = new();
matcher.AddExcludePatterns(new [] { "*.txt", "*.asciidoc", "*.md" });
此扩展方法循环访问所有代你调用 AddExclude 的模式。
多个包含项
若要添加多个包含模式,可使用:
Matcher matcher = new();
matcher.AddInclude("*.txt");
matcher.AddInclude("*.asciidoc");
matcher.AddInclude("*.md");
或者,可使用 MatcherExtensions.AddIncludePatterns(Matcher, IEnumerable<String>[]) 在单个调用中添加多个包含模式:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });
此扩展方法循环访问所有代你调用 AddInclude 的模式。
获取所有匹配文件
若要获取所有匹配文件,必须直接或间接调用 Matcher.Execute(DirectoryInfoBase)。 若要直接调用它,需要一个搜索目录:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });
string searchDirectory = "../starting-folder/";
PatternMatchingResult result = matcher.Execute(
new DirectoryInfoWrapper(
new DirectoryInfo(searchDirectory)));
// Use result.HasMatches and results.Files.
// The files in the results object are file paths relative to the search directory.
上述 C# 代码:
- 实例化 Matcher 对象。
- 调用 AddIncludePatterns(Matcher, IEnumerable<String>[]) 以添加几个要包含的文件名模式。
- 声明并分配搜索目录值。
- 从给定的 DirectoryInfo 实例化
searchDirectory
。 - 从它包装的 DirectoryInfoWrapper 中实例化
DirectoryInfo
。 - 在给定
DirectoryInfoWrapper
实例的情况下调用Execute
以生成 PatternMatchingResult 对象。
注意
DirectoryInfoWrapper
类型在 Microsoft.Extensions.FileSystemGlobbing.Abstractions
命名空间中定义,而 DirectoryInfo
类型在 System.IO
命名空间中定义。 若要避免不必要的 using
指令,可使用提供的扩展方法。
还有另一种扩展方法可生成表示匹配文件的 IEnumerable<string>
:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });
string searchDirectory = "../starting-folder/";
IEnumerable<string> matchingFiles = matcher.GetResultsInFullPath(searchDirectory);
// Use matchingFiles if there are any found.
// The files in this collection are fully qualified file system paths.
上述 C# 代码:
- 实例化 Matcher 对象。
- 调用 AddIncludePatterns(Matcher, IEnumerable<String>[]) 以添加几个要包含的文件名模式。
- 声明并分配搜索目录值。
- 在给定
searchDirectory
值的情况下调用GetResultsInFullPath
以将所有匹配文件生成为IEnumerable<string>
。
匹配重载
PatternMatchingResult 对象表示 FilePatternMatch 实例的集合,并公开一个 boolean
值,该值指示结果是否有匹配项 - PatternMatchingResult.HasMatches。
使用 Matcher
实例,可调用各种 Match
重载中的任何一个来获取模式匹配结果。 Match
方法反转了调用方的责任,即提供一个在其中评估匹配项的文件或文件集合。 换言之,调用方负责传递要匹配的文件。
重要
使用任何 Match
重载时,都不涉及文件系统 I/O。 所有文件通配都是在内存中通过 matcher
实例的包含和排除模式完成的。 Match
重载的参数不必是完全限定的路径。 如果未指定,将使用当前目录 (Directory.GetCurrentDirectory())。
匹配单个文件:
Matcher matcher = new();
matcher.AddInclude("**/*.md");
PatternMatchingResult result = matcher.Match("file.md");
上述 C# 代码:
- 在任意目录深度匹配任何带有 .md文件扩展名的文件。
- 如果名为 file.md 的文件存在于当前目录的子目录中:
result.HasMatches
将为true
。- 且
result.Files
将有一个匹配项。
其他 Match
重载的工作方式类似。
模式格式
AddExclude
和 AddInclude
方法中指定的模式可使用以下格式来匹配多个文件或目录。
确切的目录名或文件名
some-file.txt
path/to/file.txt
文件名和目录名中的通配符
*
,表示零到多个字符,不包括分隔符。值 说明 *.txt
具有 .txt 文件扩展名的所有文件。 *.*
具有一个扩展名的所有文件。 *
顶层目录中的所有文件。 .*
以“.”开头的文件名称。 *word*
文件名中包含“word”的所有文件。 readme.*
所有带有任何文件扩展名且名为“readme”的文件。 styles/*.css
目录“styles/”中扩展名为“.css”的所有文件。 scripts/*/*
“scripts/”中的或“scripts/”下一级子目录中的所有文件。 images*/*
文件夹中名称为“images”或名称以“images”开头的所有文件。 任意目录深度 (
/**/
)。值 描述 **/*
任何子目录中的所有文件。 dir/
“dir/”下任何子目录中的所有文件。 dir/**/*
“dir/”下任何子目录中的所有文件。 相对路径。
若要将同级名为“shared”的目录中的所有文件与指定给 Matcher.Execute(DirectoryInfoBase) 的基本目录相匹配,请使用
../shared/*
。
示例
请考虑下面的示例目录,以及相应文件夹中的每个文件。
📁 parent
│ file.md
│ README.md
│
└───📁 child
│ file.MD
│ index.js
│ more.md
│ sample.mtext
│
├───📁 assets
│ image.png
│ image.svg
│
└───📁 grandchild
file.md
style.css
sub.text
提示
某些文件扩展名采用大写形式,而另一些扩展名采用小写形式。 默认使用 StringComparer.OrdinalIgnoreCase。 若要指定不同的字符串比较行为,请使用 Matcher.Matcher(StringComparison) 构造函数。
获取所有文件扩展名为 .md 或 .mtext 的 Markdown 文件(不考虑字符大小写) :
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "**/*.md", "**/*.mtext" });
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
运行该应用程序将输出类似于以下内容的结果:
C:\app\parent\file.md
C:\app\parent\README.md
C:\app\parent\child\file.MD
C:\app\parent\child\more.md
C:\app\parent\child\sample.mtext
C:\app\parent\child\grandchild\file.md
在任意深度获取 assets 目录中的任何文件:
Matcher matcher = new();
matcher.AddInclude("**/assets/**/*");
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
运行该应用程序将输出类似于以下内容的结果:
C:\app\parent\child\assets\image.png
C:\app\parent\child\assets\image.svg
获取目录名在任意深度包含单词 child 且文件扩展名不是 .md、.text 或 .mtext 的任何文件 :
Matcher matcher = new();
matcher.AddInclude("**/*child/**/*");
matcher.AddExcludePatterns(
new[]
{
"**/*.md", "**/*.text", "**/*.mtext"
});
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
运行该应用程序将输出类似于以下内容的结果:
C:\app\parent\child\index.js
C:\app\parent\child\assets\image.png
C:\app\parent\child\assets\image.svg
C:\app\parent\child\grandchild\style.css