Utiliser des caractères génériques dans les fichiers dans .NET

Dans cet article, vous allez apprendre à utiliser des caractères génériques (« globbing ») dans les fichiers avec le package NuGet Microsoft.Extensions.FileSystemGlobbing. Un glob est un terme utilisé afin de définir des modèles pour la mise en correspondance des noms de fichiers et de répertoires sur la base des caractères génériques. Le « globbing » correspond à la définition d’un ou plusieurs modèles Glob et à la restitution de fichiers à partir de correspondances inclusives ou exclusives.

Modèles

Pour faire correspondre des fichiers dans le système de fichiers en fonction des modèles définis par l’utilisateur, commencez par instancier un objet Matcher. Un Matcher peut être instancié sans paramètres ou avec un paramètre System.StringComparison, qui est utilisé en interne pour comparer les modèles aux noms de fichiers. Le Matcher expose les méthodes additives suivantes :

Les méthodes AddExclude et AddInclude peuvent être appelées n’importe quel nombre de fois, afin d’ajouter différents modèles de nom de fichier à exclure ou à inclure dans les résultats. Une fois que vous avez instancié un Matcher et ajouté des modèles, il est ensuite utilisé pour évaluer les correspondances à partir d’un répertoire de départ avec la méthode Matcher.Execute.

Méthodes d’extension

L’objet Matcher a plusieurs méthodes d’extension.

Exclusions multiples

Pour ajouter plusieurs modèles d’exclusion, vous pouvez utiliser :

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

Vous pouvez également utiliser MatcherExtensions.AddExcludePatterns(Matcher, IEnumerable<String>[]) pour ajouter plusieurs modèles d’exclusion dans un seul appel :

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

Cette méthode d’extension itère sur tous les modèles fournis appelant AddExclude en votre nom.

Inclusions multiples

Pour ajouter plusieurs modèles d’inclusion, vous pouvez utiliser :

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

Vous pouvez également utiliser MatcherExtensions.AddIncludePatterns(Matcher, IEnumerable<String>[]) pour ajouter plusieurs modèles d’inclusion dans un seul appel :

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

Cette méthode d’extension itère sur tous les modèles fournis appelant AddInclude en votre nom.

Obtenir tous les fichiers correspondants

Pour obtenir tous les fichiers correspondants, vous devez appeler Matcher.Execute(DirectoryInfoBase) directement ou indirectement. Pour l’appeler directement, vous avez besoin d’un répertoire de recherche :

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.

Le code C# précédent :

Notes

Le type DirectoryInfoWrapper est défini dans l’espace de noms Microsoft.Extensions.FileSystemGlobbing.Abstractions et le type DirectoryInfo est défini dans l’espace de noms System.IO. Pour éviter les instructions using inutiles, vous pouvez utiliser les méthodes d’extension fournies.

Il existe une autre méthode d’extension qui génère un élément IEnumerable<string> représentant les fichiers correspondants :

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.

Le code C# précédent :

  • Instancie un objet Matcher.
  • Appelle AddIncludePatterns(Matcher, IEnumerable<String>[]) pour ajouter plusieurs modèles de nom de fichier à inclure.
  • Déclare et affecte la valeur du répertoire de recherche.
  • Appelle GetResultsInFullPath sur la base de la valeur searchDirectory pour générer tous les fichiers correspondants en tant que IEnumerable<string>.

Surchage de correspondances

L’objet PatternMatchingResult représente une collection d’instances FilePatternMatch et expose une valeur boolean indiquant si le résultat a des correspondances : PatternMatchingResult.HasMatches.

Avec une instance Matcher, vous pouvez appeler l’une des différentes surcharges Match pour obtenir un résultat de critères spéciaux. Les méthodes Match inversent la responsabilité de l’appelant pour fournir un fichier ou une collection de fichiers dans lesquels évaluer les correspondances. En d’autres termes, l’appelant est chargé de transmettre le fichier à mettre en correspondance.

Important

Lorsque vous utilisez l’une des surcharges Match, cela n’implique aucune E/S de système de fichiers. L’ensemble du globbing de fichier est effectué en mémoire avec les modèles d’inclusion et d’exclusion de l’instance matcher. Les paramètres des surcharges Match n’ont pas besoin d’être des chemins d’accès complets. Le répertoire actif (Directory.GetCurrentDirectory()) est utilisé en l’absence de spécification.

Pour faire correspondre un seul fichier :

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

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

Le code C# précédent :

  • Fait correspondre n’importe quel fichier avec l’extension de fichier .md, à une profondeur de répertoire arbitraire.
  • Si un fichier nommé file.md existe dans un sous-répertoire du répertoire actif :
    • result.HasMatches aurait la valeur true.
    • Et result.Files aurait une correspondance.

Les surcharges Match supplémentaires fonctionnent de manière similaire.

Formats de modèle

Les modèles spécifiés dans les méthodes AddExclude et AddInclude peuvent utiliser les formats suivants pour faire à plusieurs fichiers ou répertoires.

  • Répertoire ou nom de fichier exact

    • some-file.txt
    • path/to/file.txt
  • Caractères génériques * dans les noms de fichiers et de répertoires qui représentent zéro à plusieurs caractères, sans inclure de caractères de séparation.

    Valeur Description
    *.txt Tous les fichiers avec l’extension de fichier .txt.
    *.* Tous les fichiers avec une extension.
    * Tous les fichiers dans le répertoire de niveau supérieur.
    .* Noms de fichiers commençant par « . ».
    *word* Tous les fichiers dont le nom inclut « word ».
    readme.* Tous les fichiers nommés « readme » avec n’importe quelle extension de fichier.
    styles/*.css Tous les fichiers avec l’extension .css dans le répertoire « styles/ ».
    scripts/*/* Tous les fichiers dans « scripts/ » ou un niveau de sous-répertoire sous « scripts/ ».
    images*/* Tous les fichiers d’un dossier dont le nom est ou commence par « images ».
  • Profondeur de répertoire arbitraire (/**/).

    Valeur Description
    **/* Tous les fichiers d’un sous-répertoire.
    dir/ Tous les fichiers d’un sous-répertoire sous « dir/ ».
    dir/**/* Tous les fichiers d’un sous-répertoire sous « dir/ ».
  • Chemins relatifs.

    Pour faire correspondre tous les fichiers d’un répertoire nommé « shared » au niveau frère du répertoire de base donné à Matcher.Execute(DirectoryInfoBase), utilisez ../shared/*.

Exemples

Intéressons-nous à l’exemple de répertoire suivant et à chaque fichier dans son dossier correspondant.

📁 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

Conseil

Certaines extensions de fichier sont en majuscules, tandis que d’autres sont en minuscules. Par défaut, StringComparer.OrdinalIgnoreCase est utilisé. Pour spécifier différents comportements de comparaison de chaînes, utilisez le constructeur Matcher.Matcher(StringComparison).

Pour obtenir tous les fichiers Markdown, où l’extension de fichier est .md ou .mtext, quel que soit la casse de caractère :

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

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

L’exécution de l’application génère des résultats similaires à ce qui suit :

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

Pour obtenir tous les fichiers d’un répertoire assets à une profondeur arbitraire :

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

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

L’exécution de l’application génère des résultats similaires à ce qui suit :

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

Pour obtenir les fichiers où le nom de répertoire contient le mot child à une profondeur arbitraire, et où les extensions de fichier ne sont pas .md, .text ou .mtext :

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

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

L’exécution de l’application génère des résultats similaires à ce qui suit :

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

Voir aussi