Globbing souborů v .NET

V tomto článku se dozvíte, jak používat globbing souborů s balíčkem 📦 Microsoft.Extensions.FileSystemGlobbing NuGet. Glob je termín, který slouží k definování vzorů pro odpovídající názvy souborů a adresářů na základě zástupných znaků. Globbing je akce definování jednoho nebo více vzorů globů a získávání souborů z inkluzivních nebo exkluzivních shod.

Vzory

Pokud chcete soubory v systému souborů spárovat na základě uživatelem definovaných vzorů, začněte vytvořením instance objektu Matcher . Instanci Matcher lze vytvořit bez parametrů nebo s parametrem System.StringComparison, který se používá interně k porovnání vzorů s názvy souborů. Zpřístupňuje Matcher následující aditivní metody:

Obě metody AddExclude a AddInclude lze volat libovolný početkrát, pokud chcete přidat různé vzory názvů souborů pro vyloučení nebo zahrnutí ve výsledcích. Po vytvoření instance Matcher a přidání vzorů se pak použije k vyhodnocení shody z počátečního adresáře pomocí Matcher.Execute metody.

Metody rozšíření

Objekt Matcher má několik rozšiřujících metod.

Více vyloučení

Pokud chcete přidat více vzorů vyloučení, můžete použít:

Matcher matcher = new();
matcher.AddExclude("*.txt");
matcher.AddExclude("*.asciidoc");
matcher.AddExclude("*.md");

Alternativně můžete použít MatcherExtensions.AddExcludePatterns(Matcher, IEnumerable<String>[]) k přidání více vzorů vyloučení v jednom volání:

Matcher matcher = new();
matcher.AddExcludePatterns(new [] { "*.txt", "*.asciidoc", "*.md" });

Tato metoda rozšíření iteruje nad všemi zadanými vzory a volá AddExclude vaším jménem.

Vícenásobné zahrnutí

Pokud chcete přidat více vzorů zahrnutí, můžete použít:

Matcher matcher = new();
matcher.AddInclude("*.txt");
matcher.AddInclude("*.asciidoc");
matcher.AddInclude("*.md");

Alternativně můžete použít MatcherExtensions.AddIncludePatterns(Matcher, IEnumerable<String>[]) k přidání více vzorů zahrnutí do jednoho volání:

Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });

Tato metoda rozšíření iteruje nad všemi zadanými vzory a volá AddInclude vaším jménem.

Získání všech odpovídajících souborů

Pokud chcete získat všechny odpovídající soubory, musíte volat Matcher.Execute(DirectoryInfoBase) buď přímo, nebo nepřímo. Pokud ho chcete volat přímo, potřebujete vyhledávací adresář:

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.

Předchozí kód jazyka C#:

Poznámka:

Typ DirectoryInfoWrapper je definován v Microsoft.Extensions.FileSystemGlobbing.Abstractions oboru názvů a DirectoryInfo typ je definován v System.IO oboru názvů. Pokud se chcete vyhnout zbytečným using direktivám, můžete použít poskytnuté rozšiřující metody.

Existuje další rozšiřující metoda, která poskytuje IEnumerable<string> reprezentující odpovídající soubory:

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.

Předchozí kód jazyka C#:

  • Vytvoří instanci objektu Matcher .
  • AddIncludePatterns(Matcher, IEnumerable<String>[]) se používá k přidání několika vzorů názvů souborů ke zahrnutí.
  • Deklaruje a přiřazuje hodnotu vyhledávacího adresáře.
  • Volání GetResultsInFullPath s hodnotou searchDirectory , výsledkem čehož jsou všechny odpovídající soubory jako IEnumerable<string>.

Porovnání přetížení

Objekt PatternMatchingResult představuje kolekci FilePatternMatch instancí a zveřejňuje boolean hodnotu určující, zda výsledek odpovídá –PatternMatchingResult.HasMatches

S instancí Matcher můžete využít libovolné z různých přetížení Match, abyste získali výsledek porovnávání vzorů. Match Metody invertují odpovědnost volajícího za poskytnutí souboru nebo kolekce souborů, ve kterých se mají vyhodnotit shody. Jinými slovy, volající je zodpovědný za to, že předá soubor k vyhledání shody.

Důležité

Při použití některého z Match přetížení neprobíhá žádná operace vstupu/výstupu souborového systému. Všechny globbingy souborů se provádějí v paměti s zahrnutím a vyloučením vzorů matcher instance. Parametry přetížení Match nemusí být plně kvalifikovanými cestami. Aktuální adresář (Directory.GetCurrentDirectory()) se použije, pokud není zadaný.

Pro přiřazení jednoho souboru:

Matcher matcher = new();
matcher.AddInclude("**/*.md");

PatternMatchingResult result = matcher.Match("file.md");

Předchozí kód jazyka C#:

  • Odpovídá libovolnému souboru s příponou souboru .md s libovolnou hloubkou adresáře.
  • Pokud soubor s názvem file.md existuje v podadresáři z aktuálního adresáře:
    • result.HasMatches by to bylo true.
    • a result.Files by měla jednu shodu.

Další Match přetížení fungují podobným způsobem.

Seřazené vyhodnocení zahrnutí/vyloučení

Ve výchozím nastavení nástroj pro porovnávání vyhodnotí všechny vzory zahrnutí a pak použije všechny vzory vyloučení bez ohledu na pořadí, ve kterém jste je přidali. To znamená, že nemůžete zahrnout soubory, které byly dříve vyloučeny.

Od verze 10 📦 balíčku Microsoft.Extensions.FileSystemGlobbing se můžete rozhodnout pro seřazené vyhodnocení, kde zahrnutí a vyloučení se zpracovávají přesně v pořadí, ve kterém byly přidány:

using Microsoft.Extensions.FileSystemGlobbing;

// Preserve the order of patterns when matching.
Matcher matcher = new(preserveFilterOrder: true);

matcher.AddInclude("**/*");                // include everything
matcher.AddExclude("logs/**/*");           // exclude logs
matcher.AddInclude("logs/important/**/*"); // re-include important logs

var result = matcher.Execute(new DirectoryInfoWrapper(new DirectoryInfo(root)));
foreach (var file in result.Files)
{
    Console.WriteLine(file.Path);
}

V tomto režimu se vzory použijí po druhém:

  • **/* přidá všechny soubory.
  • logs/**/* vyfiltruje cokoli v logs/.
  • logs/important/**/* přidá zpět pouze soubory v části logs/important/.

Stávající kód, který používá výchozí konstruktor, se bude dál spouštět s původním chováním "all includes, then all excludes".

Formáty vzorů

Vzory zadané v těchto AddExclude metodách AddInclude můžou použít následující formáty, aby odpovídaly více souborům nebo adresářům.

  • Přesný název adresáře nebo souboru

    • some-file.txt
    • path/to/file.txt
  • Zástupné znaky * v názvech souborů a adresářů, které představují nula až mnoho znaků, s výjimkou znaků oddělovače.

    Hodnota Popis
    *.txt Všechny soubory s příponou .txt .
    *.* Všechny soubory s příponou.
    * Všechny soubory v adresáři nejvyšší úrovně.
    .* Názvy souborů začínající na ".".
    *word* Všechny soubory s slovem v názvu souboru.
    readme.* Všechny soubory s názvem readme s libovolnou příponou souboru.
    styles/*.css Všechny soubory s příponou ".css" v adresáři "styles/".
    scripts/*/* Všechny soubory ve složce 'scripts/' nebo v podadresáři jedné úrovně pod složkou 'scripts/'.
    images*/* Všechny soubory ve složce s názvem, který je nebo začíná na "images".
  • Hloubka libovolného adresáře (/**/).

    Hodnota Popis
    **/* Všechny soubory v libovolném podadresáři.
    dir/ Všechny soubory v libovolném podadresáři v adresáři dir/.
    dir/**/* Všechny soubory v libovolném podadresáři v adresáři dir/.
  • Relativní cesty.

    Chcete-li, aby všechny soubory v adresáři s názvem "shared" odpovídaly základnímu adresáři zadanému Matcher.Execute(DirectoryInfoBase) na stejné úrovni, použijte ../shared/*.

Příklady

Podívejte se na následující příklad adresáře a každý soubor v příslušné složce.

📁 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

Návod

Některé přípony souborů jsou velkými písmeny, zatímco jiné jsou malými písmeny. Ve výchozím nastavení StringComparer.OrdinalIgnoreCase se používá. Chcete-li zadat jiné chování porovnání řetězců, použijte Matcher.Matcher(StringComparison) konstruktor.

Pokud chcete získat všechny soubory markdownu, kde přípona souboru je .md nebo .mtext bez ohledu na velikost znaků:

Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "**/*.md", "**/*.mtext" });

foreach (string file in matcher.GetResultsInFullPath("parent"))
{
    Console.WriteLine(file);
}

Spuštění aplikace by zobrazilo výsledky podobné následujícím:

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

Pokud chcete získat jakékoli soubory v adresáři assets v libovolné hloubce:

Matcher matcher = new();
matcher.AddInclude("**/assets/**/*");

foreach (string file in matcher.GetResultsInFullPath("parent"))
{
    Console.WriteLine(file);
}

Spuštění aplikace by zobrazilo výsledky podobné následujícím:

C:\app\parent\child\assets\image.png
C:\app\parent\child\assets\image.svg

Chcete-li získat všechny soubory, kde název adresáře obsahuje slovo child v libovolné hloubce a přípony souborů nejsou .md, .text ani .mtext:

Matcher matcher = new();
matcher.AddInclude("**/*child/**/*");
matcher.AddExcludePatterns(
    new[]
    {
        "**/*.md", "**/*.text", "**/*.mtext"
    });

foreach (string file in matcher.GetResultsInFullPath("parent"))
{
    Console.WriteLine(file);
}

Spuštění aplikace by zobrazilo výsledky podobné následujícím:

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

Viz také