Globbing de arquivo no .NET
Neste artigo, você aprenderá a usar o globbing de arquivos com o Microsoft.Extensions.FileSystemGlobbing
pacote NuGet. Um glob é um termo usado para definir padrões para nomes de arquivos e diretórios correspondentes com base em curingas. Globbing é o ato de definir um ou mais padrões de glob e produzir arquivos de correspondências inclusivas ou exclusivas.
Padrões
Para corresponder arquivos no sistema de arquivos com base em padrões definidos pelo usuário, comece instanciando um Matcher objeto. A Matcher
pode ser instanciado sem parâmetros, ou com um System.StringComparison parâmetro, que é usado internamente para comparar padrões com nomes de arquivos. O Matcher
expõe os seguintes métodos aditivos:
Ambos os AddExclude
métodos podem AddInclude
ser chamados qualquer número de vezes, para adicionar vários padrões de nome de arquivo para excluir ou incluir dos resultados. Depois de instanciar um Matcher
e adicionar padrões, ele é usado para avaliar correspondências de um diretório inicial com o Matcher.Execute método.
Métodos de extensão
O Matcher
objeto tem vários métodos de extensão.
Exclusões múltiplas
Para adicionar vários padrões de exclusão, você pode usar:
Matcher matcher = new();
matcher.AddExclude("*.txt");
matcher.AddExclude("*.asciidoc");
matcher.AddExclude("*.md");
Como alternativa, você pode usar o MatcherExtensions.AddExcludePatterns(Matcher, IEnumerable<String>[]) para adicionar vários padrões de exclusão em uma única chamada:
Matcher matcher = new();
matcher.AddExcludePatterns(new [] { "*.txt", "*.asciidoc", "*.md" });
Esse método de extensão itera em todos os padrões fornecidos chamando AddExclude em seu nome.
Inclusões múltiplas
Para adicionar vários padrões de inclusão, você pode usar:
Matcher matcher = new();
matcher.AddInclude("*.txt");
matcher.AddInclude("*.asciidoc");
matcher.AddInclude("*.md");
Como alternativa, você pode usar o MatcherExtensions.AddIncludePatterns(Matcher, IEnumerable<String>[]) para adicionar vários padrões de inclusão em uma única chamada:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });
Esse método de extensão itera em todos os padrões fornecidos chamando AddInclude em seu nome.
Obter todos os arquivos correspondentes
Para obter todos os arquivos correspondentes, você tem que ligar Matcher.Execute(DirectoryInfoBase) direta ou indiretamente. Para chamá-lo diretamente, você precisa de um diretório de pesquisa:
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.
O código C# anterior:
- Instancia um Matcher objeto.
- Chamadas AddIncludePatterns(Matcher, IEnumerable<String>[]) para adicionar vários padrões de nome de arquivo para incluir.
- Declara e atribui o valor do diretório de pesquisa.
- Instancia a DirectoryInfo do dado
searchDirectory
. - Instancia um DirectoryInfoWrapper a partir do
DirectoryInfo
it wraps. - Chamadas
Execute
dadas aDirectoryInfoWrapper
instância para produzir um PatternMatchingResult objeto.
Nota
O DirectoryInfoWrapper
tipo é definido no Microsoft.Extensions.FileSystemGlobbing.Abstractions
namespace e o DirectoryInfo
tipo é definido no System.IO
namespace. Para evitar diretivas desnecessárias using
, você pode usar os métodos de extensão fornecidos.
Há outro método de extensão que produz uma IEnumerable<string>
representação dos arquivos correspondentes:
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.
O código C# anterior:
- Instancia um Matcher objeto.
- Chamadas AddIncludePatterns(Matcher, IEnumerable<String>[]) para adicionar vários padrões de nome de arquivo para incluir.
- Declara e atribui o valor do diretório de pesquisa.
- Chamadas
GetResultsInFullPath
dado osearchDirectory
valor para produzir todos os arquivos correspondentes como umIEnumerable<string>
arquivo .
Sobrecargas de correspondência
O PatternMatchingResult objeto representa uma coleção de FilePatternMatch instâncias e expõe um boolean
valor que indica se o resultado tem correspondências—PatternMatchingResult.HasMatches.
Com uma instância, você pode chamar qualquer uma Matcher
das várias Match
sobrecargas para obter um resultado de correspondência de padrão. Os Match
métodos invertem a responsabilidade do chamador de fornecer um arquivo ou uma coleção de arquivos para avaliar as correspondências. Em outras palavras, o chamador é responsável por passar o arquivo para corresponder.
Importante
Ao usar qualquer uma das sobrecargas, não há E/S do sistema de Match
arquivos envolvida. Todo o globbing de arquivo é feito na memória com os padrões include e exclude da matcher
instância. Os parâmetros das Match
sobrecargas não precisam ser caminhos totalmente qualificados. O diretório atual (Directory.GetCurrentDirectory()) é usado quando não especificado.
Para corresponder a um único ficheiro:
Matcher matcher = new();
matcher.AddInclude("**/*.md");
PatternMatchingResult result = matcher.Match("file.md");
O código C# anterior:
- Corresponde a qualquer arquivo com a extensão de arquivo .md , em uma profundidade de diretório arbitrária.
- Se existir um arquivo chamado file.md em um subdiretório do diretório atual:
result.HasMatches
seriatrue
.- e
result.Files
teria uma partida.
As sobrecargas adicionais Match
funcionam de forma semelhante.
Formatos de padrão
Os padrões especificados nos AddExclude
métodos e AddInclude
podem usar os seguintes formatos para corresponder a vários arquivos ou diretórios.
Diretório exato ou nome do arquivo
some-file.txt
path/to/file.txt
Curingas
*
em nomes de arquivos e diretórios que representam zero a muitos caracteres, não incluindo caracteres separadores.valor Description *.txt
Todos os arquivos com extensão de arquivo .txt . *.*
Todos os ficheiros com uma extensão. *
Todos os arquivos no diretório de nível superior. .*
Nomes de ficheiros que comecem por '.'. *word*
Todos os ficheiros com 'word' no nome do ficheiro. readme.*
Todos os arquivos chamados 'readme' com qualquer extensão de arquivo. styles/*.css
Todos os arquivos com extensão '.css' no diretório 'styles/'. scripts/*/*
Todos os arquivos em 'scripts/' ou um nível de subdiretório em 'scripts/'. images*/*
Todos os arquivos em uma pasta com nome que é ou começa com 'imagens'. Profundidade de diretório arbitrária (
/**/
).valor Description **/*
Todos os arquivos em qualquer subdiretório. dir/
Todos os arquivos em qualquer subdiretório em 'dir/'. dir/**/*
Todos os arquivos em qualquer subdiretório em 'dir/'. Caminhos relativos.
Para fazer a correspondência entre todos os arquivos em um diretório chamado "compartilhado" no nível irmão e o diretório base fornecido ao Matcher.Execute(DirectoryInfoBase), use
../shared/*
.
Exemplos
Considere o seguinte diretório de exemplo e cada arquivo dentro de sua pasta correspondente.
📁 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
Gorjeta
Algumas extensões de arquivo estão em maiúsculas, enquanto outras estão em minúsculas. Por padrão, StringComparer.OrdinalIgnoreCase é usado. Para especificar um comportamento de comparação de cadeia de caracteres diferente, use o Matcher.Matcher(StringComparison) construtor.
Para obter todos os arquivos de markdown, onde a extensão do arquivo é .md ou .mtext, independentemente do caso do caractere:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "**/*.md", "**/*.mtext" });
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
A execução do aplicativo produziria resultados semelhantes aos seguintes:
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
Para obter quaisquer arquivos em um diretório de ativos em uma profundidade arbitrária:
Matcher matcher = new();
matcher.AddInclude("**/assets/**/*");
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
A execução do aplicativo produziria resultados semelhantes aos seguintes:
C:\app\parent\child\assets\image.png
C:\app\parent\child\assets\image.svg
Para obter quaisquer arquivos em que o nome do diretório contenha a palavra filho em uma profundidade arbitrária e as extensões de arquivo não sejam .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);
}
A execução do aplicativo produziria resultados semelhantes aos seguintes:
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