.NET でのファイルのグロビング

この記事では、Microsoft.Extensions.FileSystemGlobbing NuGet パッケージでファイルのグロビングを使用する方法について説明します。 glob は、ワイルドカードに基づいてファイル名とディレクトリ名を照合するパターンを定義するために使用される用語です。 グロビングは、1 つまたは複数の 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>[]) を使用して、1 回の呼び出しで複数の除外パターンを追加することもできます。

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>[]) を使用して、1 回の呼び出しで複数の包含パターンを追加することもできます。

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>[]) を呼び出して、含めるファイル名のパターンをいくつか追加します。
  • 検索ディレクトリの値を宣言して割り当てます。
  • 与えられた searchDirectory から DirectoryInfo のインスタンスを作成します。
  • それがラップするDirectoryInfo から DirectoryInfoWrapper のインスタンスを作成します。
  • DirectoryInfoWrapper インスタンスを指定して Execute を呼び出し、PatternMatchingResult オブジェクトを生成します。

注意

DirectoryInfoWrapper 型は Microsoft.Extensions.FileSystemGlobbing.Abstractions 名前空間に定義され、DirectoryInfo 型は System.IO 名前空間に定義されます。 不要な using ステートメントを回避するには、提供されている拡張メソッドを使用できます。

一致するファイルを表す IEnumerable<string> を生成する拡張メソッドがもう 1 つあります。

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.HasMatchestrue になります。
    • result.Files は一致が 1 つになります。

追加の Match オーバーロードは、同様の方法で動作します。

パターンの形式

AddExclude および AddInclude メソッドで指定されるパターンは、次の形式を使用して、複数のファイルまたはディレクトリを照合することができます。

  • ディレクトリまたはファイルの正確な名前

    • some-file.txt
    • path/to/file.txt
  • ファイルおよびディレクトリ名内の * ワイルドカード。区切り文字を含まない 0 個以上の文字を表します。

    説明
    *.txt ファイル拡張子が .txt のすべてのファイル。
    *.* 拡張子を持つすべてのファイル。
    * 最上位のディレクトリにあるすべてのファイル。
    .* '.'.で始まるファイル名。
    *word* ファイル名に ' word ' が含まれるすべてのファイル。
    readme.* 任意のファイル拡張子を持つ ' readme ' という名前のすべてのファイル。
    styles/*.css ディレクトリ 'styles/' 内にあり、拡張子が '.css' のすべてのファイル。
    scripts/*/* 'scripts/' または 'scripts/' の下の 1 つのサブディレクトリ レベルにあるすべてのファイル。
    images*/* 名前が 'images' に等しいまたはそれで始まるフォルダー内のすべてのファイル。
  • 任意のディレクトリの深さ (/**/)。

    説明
    **/* 任意のサブディレクトリ内のすべてのファイル。
    dir/ 'dir/' の下の任意のサブディレクトリにあるすべてのファイル。
    dir/**/* 'dir/' の下の任意のサブディレクトリにあるすべてのファイル。
  • 相対パス。

    Matcher.Execute(DirectoryInfoBase) に与えられたベース ディレクトリの兄弟レベルにある "shared " という名前のディレクトリ内のすべてのファイルを照合するには、../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 のいずれかであるマークダウン ファイルを、大文字小文字に関係なくすべて取得するには:

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

こちらもご覧ください