.NET 中的文件通配

在本文中,了解如何将文件通配与 Microsoft.Extensions.FileSystemGlobbing NuGet 包一起使用。 glob 是一种术语,用于定义基于通配符匹配文件名和目录名的模式。 通配是定义一个或多个 glob 模式,并从包含或排除的匹配项中生成文件的操作。

模式

若要基于用户定义的模式匹配文件系统中的文件,请通过实例化 Matcher 对象开始。 Matcher 可在没有参数的情况下进行实例化,也可以使用 System.StringComparison 参数进行实例化,该参数在内部用于比较模式和文件名。 Matcher 公开以下附加方法:

AddExcludeAddInclude 方法都可以调用任意多次,以添加各种要从结果中排除或包含文件名模式。 在实例化了 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# 代码:

注意

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 重载的工作方式类似。

模式格式

AddExcludeAddInclude 方法中指定的模式可使用以下格式来匹配多个文件或目录。

  • 确切的目录名或文件名

    • 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

请参阅