IA /

IA:Patrones Glob en Claude Code

Qué es un patrón glob

Un glob es una forma compacta de describir un conjunto de rutas de fichero mediante comodines. En lugar de enumerar uno por uno los archivos que te interesan, escribes una plantilla con símbolos especiales, y el sistema se encarga de expandirla a la lista concreta.

El nombre viene de un programa antiguo de Unix llamado glob (de global), pensado precisamente para esa tarea: expandir comodines en la línea de comandos. Hoy los encontramos en decenas de sitios: la shell, .gitignore, configuración de linters, herramientas de build, y (lo que nos ocupa) los ficheros rules de Claude Code.

La clave mental es que un glob se compara contra una ruta. No es código que se ejecuta ni una expresión regular: es una plantilla que o encaja con una ruta, o no encaja.

  1.     Patrón:  src/**/*.ts
  2.     Ruta A:  src/utils/format.ts      ← encaja
  3.     Ruta B:  src/index.ts             ← encaja
  4.     Ruta C:  lib/utils/format.ts      ← NO encaja (no empieza por src/)
  5.     Ruta D:  src/components/Button.tsx ← NO encaja (extensión .tsx, no .ts)

Con esto en la cabeza, veamos los caracteres especiales uno a uno.

El asterisco simple: *

El * coincide con cualquier cadena de caracteres dentro de un mismo tramo de ruta. El matiz importante es ese "dentro de un mismo tramo": un * solitario no atraviesa separadores de directorio (/).

  1.     Patrón:  *.md
  2.     Encaja:  README.md
  3.     Encaja:  notas.md
  4.     NO:      docs/guia.md   ← está en un subdirectorio
  5.  
  6.     Patrón:  src/*.ts
  7.     Encaja:  src/index.ts
  8.     Encaja:  src/utils.ts
  9.     NO:      src/utils/helpers.ts   ← hay otro nivel de por medio
  10.     NO:      index.ts                ← no está dentro de src/

Puedes usarlo en cualquier posición, y tantas veces como quieras dentro del mismo tramo:

  • *.test.ts → cualquier .test.ts: login.test.ts, utils.test.ts
  • test-*.js → test-auth.js, test-api.js
  • components/*Form.* → components/LoginForm.tsx, components/SignupForm.jsx

El * también puede casar con la cadena vacía, aunque esto varía según la implementación. En la mayoría de sistemas modernos, file-*.txt coincide con file-.txt, y *.js no coincide con un fichero llamado solo .js (porque los archivos que empiezan por punto suelen tratarse como ocultos y requerir que el patrón empiece explícitamente por .).

El asterisco doble: **

El ** —también llamado globstar— coincide con cualquier cadena, incluyendo separadores de directorio. Es decir, atraviesa cuantos niveles haga falta.

  1.     Patrón:  **/*.ts
  2.     Encaja:  index.ts
  3.     Encaja:  src/utils.ts
  4.     Encaja:  src/components/forms/Login.ts
  5.     Encaja:  a/b/c/d/e/f/archivo.ts

La diferencia con * es fundamental y se nota sobre todo cuando el patrón lleva subdirectorios:

  • src/*.ts → solo archivos .ts DIRECTAMENTE dentro de src
  • src/**/*.ts → archivos .ts en src y en cualquier subdirectorio suyo

Tres usos típicos del doble asterisco:

Al principio, para decir "en cualquier lugar del proyecto":

  • **/node_modules → cualquier carpeta node_modules, esté donde esté
  • **/*.log → todos los logs, dé igual su ubicación

En medio, para saltar una cantidad desconocida de niveles:

  • src/**/*.test.ts → tests en src, a cualquier profundidad
  • packages/**/dist → la carpeta dist de cualquier paquete

Al final, para decir "todo lo que hay a partir de aquí":

  • docs/** → absolutamente todo dentro de docs, a cualquier profundidad
  • src/legacy/** → todo el contenido del directorio legacy

Un detalle importante: ** debe aparecer como tramo completo entre barras para comportarse como globstar. Escribir src**/foo no funciona como esperarías; lo correcto es src/**/foo.

El signo de interrogación: ?

El ? coincide con exactamente un carácter cualquiera (excepto el separador /). Es mucho más restrictivo que * y se usa cuando sabes la longitud exacta de lo que quieres hacer coincidir.

  1.     Patrón:  test?.js
  2.     Encaja:  test1.js
  3.     Encaja:  testA.js
  4.     NO:      test.js    ← falta el carácter
  5.     NO:      test10.js  ← son dos caracteres
  6.  
  7.     Patrón:  v?.?.?.md
  8.     Encaja:  v1.2.3.md
  9.     Encaja:  v9.0.1.md
  10.     NO:      v1.10.0.md  ← "10" son dos caracteres

En la práctica se usa poco, pero es útil cuando tienes archivos con un formato de nombre muy estricto, como versiones cortas o identificadores de longitud fija.

Clases de caracteres: [...]

Los corchetes permiten especificar un conjunto de caracteres aceptables para una sola posición. Coincide exactamente con uno de los caracteres listados.

  1.     Patrón:  [abc]rchivo.txt
  2.     Encaja:  archivo.txt
  3.     Encaja:  brchivo.txt
  4.     Encaja:  crchivo.txt
  5.     NO:      drchivo.txt

Puedes usar rangos con guion:

  1.     [0-9]     → cualquier dígito
  2.     [a-z]     → cualquier minúscula
  3.     [A-Z]     → cualquier mayúscula
  4.     [a-zA-Z]  → cualquier letra
  5.     [0-9a-f]  → cualquier dígito hexadecimal

Ejemplos realistas:

  • log-[0-9].txt → log-0.txt hasta log-9.txt
  • v[0-9].[0-9].ts → v1.0.ts, v2.3.ts, v9.9.ts...
  • test-[a-z].spec.js → test-a.spec.js, test-b.spec.js...
  • [A-Z]*.md → ficheros .md que empiezan por mayúscula

Negación dentro de los corchetes

Si el primer carácter dentro de los corchetes es ! (o ^, según la implementación), el significado se invierte: coincide con cualquier carácter que NO esté en el conjunto.

  • [!0-9]*.txt → .txt cuyo nombre NO empieza por un dígito
  • [!_]*.js → .js cuyo nombre NO empieza por guion bajo

Cuidado: la negación dentro de corchetes afecta solo a esa posición, no al patrón entero. Para negar un patrón completo se usa otra sintaxis distinta, que veremos más abajo.

Alternativas: {...}

Las llaves permiten listar varias alternativas separadas por comas, y el patrón encaja si la ruta coincide con cualquiera de ellas. Es como un "OR".

  1.     Patrón:  *.{js,ts}
  2.     Encaja:  app.js
  3.     Encaja:  app.ts
  4.     NO:      app.jsx

Esto es especialmente útil para agrupar extensiones o nombres relacionados:

  1.     *.{jpg,jpeg,png,gif,webp}   → cualquier formato de imagen común
  2.     {Dockerfile,docker-compose.yml}  → ficheros de Docker
  3.     src/**/*.{test,spec}.ts     → tests escritos con cualquiera de las dos convenciones

Las alternativas pueden contener tramos de ruta completos:

  • {src,lib,packages}/**/*.ts → TS en cualquiera de los tres directorios

Y pueden anidarse, aunque si empiezas a hacer eso probablemente tu patrón ya sea demasiado complejo y convenga partirlo en varios:

  • src/**/*.{test,spec}.{js,ts,jsx,tsx}

Algunas implementaciones aceptan también rangos numéricos con dos puntos:

  • log-{1..5}.txt → log-1.txt, log-2.txt, log-3.txt, log-4.txt, log-5.tx

Pero esto no está disponible en todos los sistemas, así que conviene no depender de ello si quieres portabilidad.

Negación de patrón: !patrón

Muchos sistemas que usan globs para seleccionar ficheros permiten también excluir mediante patrones negados que empiezan por !. La idea es: primero incluyes un conjunto amplio, y luego recortas lo que no quieres.

  1.     **/*.ts        → incluye todos los TS
  2.     !**/*.test.ts  → excepto los tests
  3.     !**/node_modules/**  → y nunca nada de node_modules

Esta sintaxis es la misma que usa .gitignore y se aplica en la mayoría de contextos donde los globs forman una lista ordenada. La regla general: cada patrón se evalúa en orden, y los patrones negados restan del conjunto acumulado hasta ese momento.

Es útil saber que la negación de patrón (! al principio) es un concepto distinto de la negación dentro de corchetes ([!abc]): la primera excluye rutas completas, la segunda solo afecta a una posición de carácter.

Combinaciones útiles: ejemplos comentados

Con estos pocos caracteres —*, **, ?, [], {}, !— se puede expresar prácticamente cualquier selección razonable de ficheros. Lo que al principio cuesta es combinarlos. Veamos una batería de ejemplos comentados:

Todos los ficheros de código TypeScript del proyecto, sin los tests:

  1.     **/*.ts
  2.     !**/*.test.ts
  3.     !**/*.spec.ts

Solo los componentes React del directorio src:

  • src/**/*.{jsx,tsx}

Ficheros de configuración en la raíz del proyecto:

  • *.{json,yaml,yml,toml}

Todos los README, estén donde estén:

  • **/README.md
  • **/README ← sin extensión, por si acaso

Migraciones de base de datos numeradas:

  • db/migrations/[0-9][0-9][0-9][0-9]_*.sql

(Coincide con 0001_init.sql, 0042_add_users.sql, etc.)

Scripts de shell en bin/, cualquier profundidad:

  • bin/**/*.{sh,bash,zsh}

Cualquier fichero dentro de un directorio __tests__:

  • **/__tests__/**

Ficheros Markdown, pero solo los de documentación (no el README):

  • docs/**/*.md
  • !docs/**/DRAFT-*.md

Archivos de estilo, cualquier preprocesador:

  • **/*.{css,scss,sass,less,styl}

Todo el código fuente menos lo generado:

  • src/**
  • !src/**/generated/**
  • !src/**/*.generated.*

Errores habituales y cómo evitarlos

Hay cuatro tropiezos que vienen una y otra vez cuando uno empieza con globs. Merece la pena tenerlos presentes.

Confundir * con **. El error clásico: escribir src/*.ts esperando que cubra todo src y quedarse sorprendido de que los ficheros en subdirectorios no entran. Regla mental: un asterisco no cruza barras, dos sí. En cuanto veas que tu patrón "no recoge lo de dentro de las carpetas", cambia el * por **/*.

Olvidar que ** necesita estar aislado por barras. Escribir src** o **foo no funciona como globstar en la mayoría de implementaciones. El globstar quiere vivir solo entre separadores: src/**/foo, no src**/foo.

Pensar que los globs son regex. No lo son. En un glob, el punto . es un punto literal, no "cualquier carácter". app.js en un glob significa exactamente app.js. Y no existen cuantificadores tipo + o {3,5}: si quieres algo así, necesitas combinar ? y * de otra manera, o aceptar que los globs no están diseñados para esto.

No pensar en los ficheros ocultos. Los archivos que empiezan por punto (.env, .gitignore, .config/) suelen estar fuera de lo que captura un patrón genérico. Un *.json no tiene por qué capturar .babelrc.json en muchas implementaciones. Si los quieres incluir, sé explícito: .* o **/.*.

Referencia rápida

Un resumen para tener a mano mientras escribes patrones:

  • * — Cualquier cadena dentro de un tramo de ruta, sin cruzar barras. Ejemplo: *.ts coincide con index.ts o utils.ts.
  • ** — Cualquier cadena, atravesando directorios. Ejemplo: src/**/*.ts coincide con src/a/b/c.ts.
  • ? — Exactamente un carácter cualquiera. Ejemplo: v?.md coincide con v1.md o vA.md, pero no con v10.md.
  • [abc] — Uno de los caracteres listados. Ejemplo: [abc].js coincide con a.js, b.js o c.js.
  • [a-z] — Un carácter dentro del rango. Ejemplo: [0-9].txt coincide con 0.txt hasta 9.txt.
  • [!abc] — Un carácter que NO está en el conjunto. Ejemplo: [!_]*.js excluye los que empiezan por guion bajo.
  • {a,b} — Alternativas, funciona como un OR. Ejemplo: *.{js,ts} coincide con app.js o app.ts.
  • !patrón — Excluye rutas que encajen con el patrón. Ejemplo: !**/*.test.ts deja fuera los tests.

Cómo aplicarlo a tus rules

Vuelve a los ficheros de rules que vimos en la clase anterior y piensa en qué ámbito quieres que actúe cada uno. El glob no es un adorno: es lo que determina si tu regla se activará con el fichero que el usuario tenga abierto o no.

Un buen ejercicio es, para cada regla que escribas, preguntarte tres cosas: ¿qué ficheros exactos deberían dispararla?, ¿qué ficheros parecidos deberían quedar fuera?, y ¿hay algún subdirectorio "trampa" (node_modules, dist, build, .next) que convenga excluir explícitamente? Escribir el glob después de responder estas tres preguntas te sale casi solo.

Y si dudas entre dos patrones, casi siempre el bueno es el más específico que sigue cubriendo los casos que te importan. Un glob demasiado amplio activará la regla donde no toca y generará ruido; uno demasiado estrecho dejará sin cubrir casos legítimos. Afina hasta que encaje.


IA : Prompts : Claude : Copilot

Última modificación de la página el 20 May 2026 a las 19h19
Powered by PmWiki