Comodines de archivos en .NET
En este artículo, aprenderá a usar comodines de archivos con el paquete NuGet Microsoft.Extensions.FileSystemGlobbing
. Un patrón global es un término que se usa para definir patrones a fin de buscar coincidencias de nombres de archivos y directorios en función de caracteres comodín. El uso de comodines consiste en definir uno o varios patrones globales y generar archivos a partir de coincidencias inclusivas o exclusivas.
Patrones
Para hacer coincidir los archivos del sistema de archivos en función de patrones definidos por el usuario, empiece por crear instancias de un objeto Matcher. Se puede crear una instancia de Matcher
sin parámetros o con un parámetro System.StringComparison, que se usa internamente para comparar patrones con nombres de archivo. Matcher
expone los métodos aditivos siguientes:
Se puede llamar a los métodos AddExclude
y AddInclude
cualquier número de veces, a fin de agregar varios patrones de nombre de archivo que excluir de los resultados o incluir en estos. Una vez que haya creado una instancia de Matcher
y agregado patrones, se usará para evaluar las coincidencias de un directorio inicial con el método Matcher.Execute.
Métodos de extensión
El objeto Matcher
tiene varios métodos de extensión.
Varias exclusiones
Para agregar varios patrones de exclusión, puede usar lo siguiente:
Matcher matcher = new();
matcher.AddExclude("*.txt");
matcher.AddExclude("*.asciidoc");
matcher.AddExclude("*.md");
Como alternativa, puede usar MatcherExtensions.AddExcludePatterns(Matcher, IEnumerable<String>[]) para agregar varios patrones de exclusión en una sola llamada:
Matcher matcher = new();
matcher.AddExcludePatterns(new [] { "*.txt", "*.asciidoc", "*.md" });
Este método de extensión itera por todos los patrones proporcionados y llama a AddExclude en su nombre.
Varias inclusiones
Para agregar varios patrones de inclusión, puede usar lo siguiente:
Matcher matcher = new();
matcher.AddInclude("*.txt");
matcher.AddInclude("*.asciidoc");
matcher.AddInclude("*.md");
Como alternativa, puede usar MatcherExtensions.AddIncludePatterns(Matcher, IEnumerable<String>[]) para agregar varios patrones de inclusión en una sola llamada:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "*.txt", "*.asciidoc", "*.md" });
Este método de extensión itera por todos los patrones proporcionados y llama a AddInclude en su nombre.
Obtención de todos los archivos coincidentes
Para obtener todos los archivos coincidentes, tendrá que llamar a Matcher.Execute(DirectoryInfoBase) de forma directa o indirecta. Para llamar al objeto directamente, necesita un directorio de búsqueda:
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.
El código de C# anterior:
- Crea instancias de un objeto Matcher.
- Llama a AddIncludePatterns(Matcher, IEnumerable<String>[]) para agregar varios patrones de nombre de archivo que se van a incluir.
- Declara y asigna el valor del directorio de búsqueda.
- Crea una instancia de DirectoryInfo a partir del objeto
searchDirectory
proporcionado. - Crea una instancia de DirectoryInfoWrapper a partir del objeto
DirectoryInfo
que encapsula. - Llama a
Execute
dada la instancia deDirectoryInfoWrapper
para generar un objeto PatternMatchingResult.
Nota
El tipo DirectoryInfoWrapper
se define en el espacio de nombres Microsoft.Extensions.FileSystemGlobbing.Abstractions
y el tipo DirectoryInfo
, en el espacio de nombres System.IO
. Para evitar directivas using
innecesarias, puede usar los métodos de extensión proporcionados.
Hay otro método de extensión que devuelve una interfaz IEnumerable<string>
que representa los archivos coincidentes:
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.
El código de C# anterior:
- Crea instancias de un objeto Matcher.
- Llama a AddIncludePatterns(Matcher, IEnumerable<String>[]) para agregar varios patrones de nombre de archivo que se van a incluir.
- Declara y asigna el valor del directorio de búsqueda.
- Llama a
GetResultsInFullPath
dado el valorsearchDirectory
para que genere todos los archivos coincidentes comoIEnumerable<string>
.
Coincidencia de sobrecargas
El objeto PatternMatchingResult representa una colección de instancias de FilePatternMatch y expone un valor boolean
que indica si el resultado tiene coincidencias:PatternMatchingResult.HasMatches.
Con una instancia de Matcher
, puede llamar a cualquiera de las distintas sobrecargas de Match
para obtener un resultado de coincidencia de patrones. Los métodos Match
invierten la responsabilidad del autor de la llamada de proporcionar un archivo o una colección de archivos para evaluar las coincidencias. Es decir, el autor de la llamada es responsable de pasar el archivo sobre el que realizar la coincidencia.
Importante
Cuando se usa cualquiera de las sobrecargas de Match
, no hay ninguna E/S del sistema de archivos implicada. Todo el uso de comodines de archivos se realiza en memoria con los patrones de inclusión y exclusión de la instancia de matcher
. Los parámetros de las sobrecargas de Match
no tienen que ser rutas completas. Si no se especifica, se usa el directorio actual (Directory.GetCurrentDirectory()).
Para hacer coincidir con un único archivo:
Matcher matcher = new();
matcher.AddInclude("**/*.md");
PatternMatchingResult result = matcher.Match("file.md");
El código de C# anterior:
- Compara cualquier archivo con la extensión de archivo .md, en una profundidad de directorio arbitraria.
- Si existe un archivo con el nombre file.md en un subdirectorio del directorio actual:
result.HasMatches
seríatrue
.- y
result.Files
tendría una coincidencia.
Las sobrecargas de Match
adicionales funcionan de maneras similares.
Formatos de patrón
Los patrones especificados en los métodos AddExclude
y AddInclude
pueden usar los formatos siguientes para comparar varios archivos o directorios.
Nombre exacto del directorio o archivo
some-file.txt
path/to/file.txt
Caracteres comodín
*
en nombres de archivos y directorios que representan de cero a varios caracteres sin incluir caracteres separadores.Value Descripción *.txt
Todos los archivos con la extensión de archivo .txt. *.*
Todos los archivos con una extensión. *
Todos los archivos del directorio de nivel superior. .*
Nombres de archivo que comienzan por ".". *word*
Todos los archivos con "word" en el nombre de archivo. readme.*
Todos los archivos denominados "léame" con cualquier extensión de archivo. styles/*.css
Todos los archivos con la extensión ".css" en el directorio "styles/". scripts/*/*
Todos los archivos de "scripts/" o un nivel de subdirectorio debajo de "scripts/". images*/*
Todos los archivos de una carpeta cuyo nombre sea o comience por "images". Profundidad arbitraria de directorio (
/**/
).Value Descripción **/*
Todos los archivos de cualquier subdirectorio. dir/
Todos los archivos de cualquier subdirectorio debajo de "dir/". dir/**/*
Todos los archivos de cualquier subdirectorio debajo de "dir/". Rutas relativas.
Para comparar todos los archivos de un directorio denominado "shared" del mismo nivel con el directorio base proporcionado a Matcher.Execute(DirectoryInfoBase), use
../shared/*
.
Ejemplos
Tenga en cuenta el directorio de ejemplo siguiente y cada archivo dentro de su carpeta correspondiente.
📁 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
Sugerencia
Algunas extensiones de archivo están en mayúsculas, mientras que otras están en minúsculas. De forma predeterminada, se usa StringComparer.OrdinalIgnoreCase. Para especificar otro comportamiento de comparación de cadenas use el constructor Matcher.Matcher(StringComparison).
Para obtener todos los archivos Markdown, donde la extensión de archivo es .md o .mtext, independientemente del uso de mayúsculas y minúsculas:
Matcher matcher = new();
matcher.AddIncludePatterns(new[] { "**/*.md", "**/*.mtext" });
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
La ejecución de la aplicación generaría una salida similar a la siguiente:
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 obtener los archivos de un directorio assets a una profundidad arbitraria:
Matcher matcher = new();
matcher.AddInclude("**/assets/**/*");
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
La ejecución de la aplicación generaría una salida similar a la siguiente:
C:\app\parent\child\assets\image.png
C:\app\parent\child\assets\image.svg
Para obtener los archivos en los que el nombre del directorio contiene la palabra child (secundario) a una profundidad arbitraria y las extensiones de archivo no son .md, .text ni .mtext:
Matcher matcher = new();
matcher.AddInclude("**/*child/**/*");
matcher.AddExcludePatterns(
new[]
{
"**/*.md", "**/*.text", "**/*.mtext"
});
foreach (string file in matcher.GetResultsInFullPath("parent"))
{
Console.WriteLine(file);
}
La ejecución de la aplicación generaría una salida similar a la siguiente:
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