Acabàvem la lliçó anterior amb una afirmació que semblava una curiositat i és en realitat la clau d'aquesta lliçó: quan escrius rm *.csv, no és rm qui entén l'asterisc. És Bash qui l'expandeix abans d'executar res, i rm ja rep la llista completa de noms. Entendre aquest repartiment de responsabilitats explica comportaments que d'una altra manera semblen màgics o arbitraris, i evita accidents que han costat sistemes sencers. Aquí aprendràs a seleccionar fitxers per patrons amb precisió sobre /var/log/veloz i l'històric de /srv/veloz/dades.
Contingut
- Què és el globbing i qui el fa
- Els comodins bàsics:
*,?i[...] - Classes de caràcters POSIX
- Expansió de claus:
{} - Globbing davant d'expressions regulars
- Ajustar el comportament amb
shopt - Què passa quan un patró no casa amb res
- Perills clàssics
- Casos pràctics sobre les dades de Veloz Envíos
- Què és el globbing i qui el fa
El globbing (o expansió de camins) és el mecanisme pel qual el shell substitueix un patró per la llista ordenada de noms de fitxer existents que hi encaixen. Té lloc durant la fase d'expansions que vas estudiar a 01-04, just abans de buscar i executar l'ordre.
La demostració definitiva és echo, que es limita a imprimir els arguments que rep:
echo no sap res de comodins. Ha rebut tres arguments ja expandits, perquè Bash ha reemplaçat el patró abans d'invocar-lo. Exactament el mateix passa amb ls, cp o rm: tots reben la llista final.
Tres conseqüències que has d'interioritzar:
- El patró només casa amb fitxers que existeixen. Si escrius
*.logen un directori sense fitxers.log, no hi ha res a substituir (secció 7). - L'expansió té lloc al directori actual, tret que el patró inclogui un camí:
/var/log/veloz/*.logfunciona des de qualsevol lloc. - Les cometes desactiven el globbing.
echo "*.csv"imprimeix literalment*.csv, perquè el patró entre cometes no s'expandeix. Aquest és el motiu pel qualgrep "*.csv" fitxerno fa el que esperes ifind . -name "*.csv"sí: afindvolem que el patró arribi sense expandir al programa.
- Els comodins bàsics:
*, ? i [...]
*, ? i [...]| Patró | Casa amb | Exemple |
|---|---|---|
* |
Qualsevol seqüència de caràcters, inclosa la buida | enviaments* → enviaments.csv, enviaments-2026-08-01.csv |
? |
Exactament un caràcter qualsevol | enviaments-2026-08-0?.csv → dies 01 a 09 |
[abc] |
Un caràcter dels llistats | log[123].txt |
[a-z] |
Un caràcter del rang | [a-m]* → noms que comencen de la a a la m |
[!0-9] |
Un caràcter que no sigui al conjunt | [!e]* → noms que no comencen per e |
ls /var/log/veloz/*.log # tots els registres
ls enviaments-2026-08-0?.csv # els nou primers dies del mes
ls enviaments-2026-0[78]-*.csv # només juliol i agost
ls enviaments-2026-08-[12][0-9].csv # dies 10 a 29Dos matisos importants:
*no travessa barres./var/log/*llista el que hi ha a/var/log, però no baixa als seus subdirectoris. Per a això hi haglobstar(secció 6).*no casa amb els fitxers ocults (els que comencen per.).ls *no mostra.bashrc. És una protecció deliberada: sense ella,rm *al teu$HOMEesborraria tota la teva configuració. Es canvia ambdotglob, però poques vegades convé.
A [!0-9], el signe ! nega el conjunt. També s'accepta ^ a Bash, però ! és la forma estàndard i portable.
- Classes de caràcters POSIX
Escriure [a-zA-Z] funciona en anglès, però es trenca amb accents i depèn de la configuració regional. Les classes POSIX són la forma robusta:
| Classe | Casa amb |
|---|---|
[[:digit:]] |
Dígits 0-9 |
[[:alpha:]] |
Lletres, incloses les accentuades de l'idioma actiu |
[[:alnum:]] |
Lletres i dígits |
[[:upper:]] / [[:lower:]] |
Majúscules / minúscules |
[[:space:]] |
Espais, tabuladors i salts de línia |
[[:punct:]] |
Signes de puntuació |
ls enviaments-[[:digit:]][[:digit:]][[:digit:]][[:digit:]]-*.csv # any de 4 dígits
ls informe-[[:upper:]]* # comença per majúsculaFixa't en el doble claudàtor: la classe és [:digit:] i va dins d'un conjunt [...], d'aquí [[:digit:]]. Les pots combinar: [[:digit:]_-] casa amb un dígit, un guió baix o un guió.
- Expansió de claus:
{}
{}L'expansió de claus s'assembla al globbing, però és una altra cosa diferent i més poderosa: genera cadenes de text sense consultar el disc i té lloc abans que el globbing, a la primera fase d'expansions.
echo {1..5} # → 1 2 3 4 5
echo {gen,feb,mar} # → gen feb mar
echo enviaments-2026-0{7,8} # → enviaments-2026-07 enviaments-2026-08Cap d'aquests noms no ha d'existir necessàriament: l'expansió de claus fabrica text, no selecciona fitxers. Per això serveix per crear coses, mentre que el globbing només serveix per seleccionar el que ja hi és:
mkdir -p ~/veloz-ops/{bin,lib,etc,logs} # crea 4 directoris
mkdir -p /srv/veloz/dades/historic/2026/{01..12} # crea els 12 mesos, amb zero al davantEl rang admet pas: {1..20..5} dóna 1 6 11 16, i també funciona amb lletres: {a..e}.
L'idiom més útil de tots és fitxer{,.bak}, que s'expandeix a fitxer fitxer.bak:
Bash converteix això en cp -a ~/veloz-ops/etc/veloz-ops.conf ~/veloz-ops/etc/veloz-ops.conf.bak. És la forma abreujada de la còpia de seguretat ràpida de la lliçó 02-01, i la veuràs constantment en documentació i en la feina de gent experimentada. Funciona perquè la primera alternativa és buida (res entre { i ,).
Un advertiment: l'expansió de claus no es produeix si hi ha espais a dins ni si només hi ha un element. echo {a} imprimeix {a} literal.
- Globbing davant d'expressions regulars
*.csv com a patró de globbing i .*\.csv com a expressió regular fan el mateix, però escrits de manera diferent i amb regles incompatibles. Confondre'ls és un error clàssic, perquè els mateixos símbols signifiquen coses diferents.
| Aspecte | Globbing (comodins) | Expressions regulars |
|---|---|---|
| Qui l'interpreta | El shell, abans d'executar | El programa (grep, sed, awk) |
| Sobre què actua | Noms de fitxer existents | Text de qualsevol procedència |
* |
Qualsevol seqüència de caràcters | «Zero o més vegades allò anterior» |
? |
Exactament un caràcter | «Zero o una vegada allò anterior» (a ERE) |
. |
Un punt literal | Un caràcter qualsevol |
| Un caràcter qualsevol | ? |
. |
| Qualsevol seqüència | * |
.* |
| Coincidència | Ha de casar el nom complet | N'hi ha prou que casi una part |
ls *.log # globbing: fitxers acabats en .log
grep '^2026-08-03.*ERROR' /var/log/veloz/app.log # regex: línies del dia amb ERROREn el segon cas, les cometes simples són imprescindibles: impedeixen que el shell intenti expandir * com a comodí i garanteixen que l'expressió arribi intacta a grep. Les expressions regulars completes s'estudien a 05-04; de moment n'hi ha prou que distingeixis el terreny de cadascuna.
- Ajustar el comportament amb
shopt
shoptshopt (shell options) activa (-s) i desactiva (-u) opcions de Bash que canvien com funciona el globbing.
| Opció | Què fa |
|---|---|
nullglob |
Si el patró no casa, s'expandeix a res en lloc de quedar-se literal |
failglob |
Si el patró no casa, l'ordre no s'executa i es mostra un error |
dotglob |
Inclou els fitxers ocults a les expansions |
nocaseglob |
Ignora majúscules i minúscules en casar |
globstar |
Habilita ** per recórrer subdirectoris recursivament |
extglob |
Habilita patrons estesos com !(*.bak) o `+(a |
shopt -s globstar
ls /var/log/veloz/**/*.log # tots els .log a qualsevol profunditat
shopt # consultar l'estat de totes les opcionsglobstar mereix atenció: ** recorre l'arbre sencer, així que **/*.csv troba els CSV de tots els subdirectoris de l'històric sense necessitat de find. Ves amb compte amb ell en arbres enormes, perquè pot trigar molt.
nocaseglob resol un cas real: si algun fitxer va arribar com a Enviaments-2026-08-01.CSV, amb l'opció activa *.csv el trobarà igualment.
Aquestes opcions són persistents a la sessió: s'activen a ~/.bashrc per a l'ús interactiu o al principi d'un script perquè el seu comportament sigui explícit.
- Què passa quan un patró no casa amb res
Aquest és el comportament per defecte més contraintuïtiu de Bash:
No hi ha cap fitxer .xml, i en lloc de retornar una llista buida, Bash deixa el patró tal qual i el passa com a argument literal. És una herència històrica i la causa d'errors desconcertants: ls *.xml respon ls: no s'ha pogut accedir a '*.xml': El fitxer o directori no existeix, i esmenta un fitxer anomenat literalment *.xml que evidentment no existeix. Encara pitjor és el que passa en un bucle:
El bucle s'executa una vegada amb el patró sense expandir com si fos un nom de fitxer, en lloc de no executar-se cap. Si a dins hi hagués un rm "$f" o una lectura del fitxer, el resultat seria un error incomprensible. Els bucles s'estudien a 04-01, però el problema és de globbing i la seva solució també:
Amb nullglob, un patró sense coincidències s'expandeix a zero arguments i el bucle no itera. És l'opció que has d'activar en qualsevol script que recorri fitxers per patró. L'alternativa failglob és encara més estricta: avorta l'ordre amb un error explícit, útil quan l'absència de fitxers indica un problema real.
- Perills clàssics
L'espai de més a rm *. Aquest és l'accident més famós d'Unix:
rm *.bak # esborra les còpies de seguretat
rm * .bak # ← esborra TOT el directori, i després es queixa que no existeix ".bak"Un sol espai converteix «esborra els .bak» en «esborra-ho tot». rm processa els arguments en ordre, així que quan mostra l'error sobre .bak ja ha esborrat el contingut del directori. Costum que ho evita: substituir rm per ls i revisar la llista abans.
Fitxers que comencen per guió. Si el directori conté un fitxer anomenat -rf, l'expansió de rm * el col·loca entre els arguments i rm l'interpreta com una opció. La protecció, ja vista a 02-01, és rm -- * o rm ./*.
rm -rf $DIR/* amb la variable buida. Si DIR no està definida, el shell expandeix la línia a rm -rf /*. És la causa documentada de diversos esborrats catastròfics en producció, i es preveu amb les tècniques de cometes i valors per defecte del Mòdul 3.
Comodins en camins absoluts amplis. rm /var/log/veloz/* sembla acotat, però si escrius /var/log/* per error l'abast canvia completament. Com més amunt sigui el directori, més a poc a poc cal escriure.
- Casos pràctics sobre les dades de Veloz Envíos
# 1. Veure tots els registres de l'aplicació, inclosos els rotats
ls -lh /var/log/veloz/*.log*
# 2. Comptar els CSV arxivats d'agost de 2026
ls /srv/veloz/dades/historic/2026/08/enviaments-2026-08-??.csv | wc -l
# 3. Copiar les dades de la primera quinzena a un directori d'anàlisi
mkdir -p ~/veloz-ops/tmp/quinzena
cp -a /srv/veloz/dades/historic/2026/08/enviaments-2026-08-{01..15}.csv \
~/veloz-ops/tmp/quinzena/
# 4. Buscar ERROR a tots els registres de l'arbre (requereix globstar)
shopt -s globstar
grep -l ERROR /var/log/veloz/**/*.log
# 5. Còpia de seguretat de tota la configuració del toolkit
cp -a ~/veloz-ops/etc/veloz-ops.conf{,.$(date +%F).bak}El cas 3 barreja els dos mecanismes i és un bon resum de la lliçó: {01..15} és expansió de claus, que genera quinze noms de text sense mirar el disc; tot seguit aquests noms es resolen contra fitxers reals. Si algun dels quinze dies no existís, cp donaria un error per aquest fitxer concret —a diferència d'un patró *, que simplement no l'hauria inclòs—. Aquest comportament és un avantatge: t'avisa que falta un dia a l'històric, que és justament el que voldries saber.
Errors Habituals i Consells
- Creure que l'ordre interpreta el comodí. Ho fa el shell. Comprova-ho sempre amb
echoal davant abans d'una operació destructiva. - Posar entre cometes un patró que volies expandir, o al revés.
rm "*.log"busca un fitxer anomenat literalment*.log;find . -name *.logsense cometes falla perquè el shell l'expandeix abans quefindel vegi. - Esperar que
*inclogui els ocults. No ho fa, i això és bo. Si de debò els necessites,shopt -s dotglob. - Confondre l'
*de globbing amb l'*d'expressió regular. En un patró de fitxer és «qualsevol cosa»; en una regex és «zero o més repeticions de l'element anterior». - Escriure bucles sobre patrons sense
nullglob. Iteraran una vegada sobre el patró literal quan no hi hagi coincidències. - Fer servir
**senseglobstar. Sense l'opció activada,**es comporta exactament igual que*i no recorre subdirectoris; la fallada és silenciosa. - Un espai de més abans del comodí. Revisa dues vegades qualsevol línia que combini
rmi*.
Exercicis
Exercici 1 — Seleccionar amb precisió. A /srv/veloz/dades/historic/2026/08 hi ha fitxers enviaments-2026-08-01.csv a enviaments-2026-08-31.csv, més un enviaments-2026-08-03.csv.bak i un notes.txt. Escriu el patró que selecciona: (a) tots els CSV del mes, sense el .bak; (b) només els dies del 20 al 29; (c) tots els fitxers del mes que no comencin per e; (d) els dies acabats en 1 o 5.
Exercici 2 — Claus davant de comodins. Explica la diferència de resultat entre aquestes dues ordres en un directori que conté només enviaments-2026-08-01.csv i enviaments-2026-08-02.csv, i digues quina faries servir per detectar un dia que falta a l'històric:
Exercici 3 — Preparar un script segur. Escriuràs un script que arxivi tots els fitxers .log de ~/veloz-ops/logs. Indica quines opcions de shopt activaries i per què, i mostra com comprovaries sense risc quins fitxers es veurien afectats abans d'executar res.
Solucions
Solució a l'Exercici 1
ls enviaments-2026-08-??.csv # (a) exactament dos dígits i acaba en .csv
ls enviaments-2026-08-2[0-9].csv # (b) dies 20 a 29
ls [!e]* # (c) no comencen per e → notes.txt
ls enviaments-2026-08-?[15].csv # (d) segon dígit 1 o 5: 01,05,11,15,21,25,31A (a), el truc és a ??: en exigir exactament dos caràcters abans de .csv, s'exclou automàticament enviaments-2026-08-03.csv.bak, perquè aquest nom té més text al darrere. Un patró enviaments*.csv hauria fallat en el sentit contrari, i enviaments* hauria inclòs el .bak.
Solució a l'Exercici 2
El primer llista, sense més, enviaments-2026-08-01.csv enviaments-2026-08-02.csv. El segon llista aquests dos i a més imprimeix tres errors: ls: no s'ha pogut accedir a 'enviaments-2026-08-03.csv': El fitxer o directori no existeix, i el mateix per al 04 i el 05.
El globbing consulta el disc i retorna només el que existeix: per definició no et pot informar mai d'una absència. L'expansió de claus genera els cinc noms a cegues i deixa que ls es queixi dels tres que no hi són. Per tant, per detectar dies que falten a l'històric es fa servir la segona forma: els errors són precisament el resultat que busques. És un bon exemple que «produir un error» pot ser el comportament desitjat.
Solució a l'Exercici 3
shopt -s nullglob # si no hi ha .log, el bucle no itera en lloc de fer-ho una vegada
shopt -s failglob # ALTERNATIVA: avorta amb error si no hi ha coincidències
shopt -u dotglob # assegurar-se de no arrossegar fitxers ocults
# Comprovació sense risc, abans de tocar res
cd ~/veloz-ops/logs
echo *.log # veure la llista exacta que rebria l'ordre
ls -lh *.log # veure a més mida i data de cadascunnullglob és l'elecció correcta per a un script d'arxivat rutinari: si un dia no hi ha registres per arxivar, l'esperable és que l'script no faci res, no que falli. failglob seria preferible en un script en què l'absència de fitxers indiqués una anomalia —per exemple, si veloz-api sempre ha de generar registres i no n'hi ha cap—, perquè llavors el silenci seria el pitjor resultat possible. Totes dues resolen el mateix problema amb criteris oposats, i triar bé depèn de si «no hi ha fitxers» és normal o alarmant en el teu cas.
La comprovació amb echo és l'hàbit clau: mostra exactament la llista d'arguments que rebrà l'ordre real, amb el mateix patró, al mateix directori i amb les mateixes opcions de shell actives.
Conclusió
Ara saps que els comodins els expandeix el shell i no l'ordre, i has comprovat amb echo que quan rm o cp s'executen ja reben la llista completa de noms. Manegues *, ?, els conjunts [...] amb negació i rangs, i les classes POSIX robustes davant dels accents. Distingeixes l'expansió de claus —que fabrica text sense mirar el disc, i per això serveix per crear i per detectar absències— del globbing, que només selecciona el que existeix. Saps en què es diferencien comodins i expressions regulars, ajustes el comportament amb shopt (nullglob, failglob, dotglob, nocaseglob, globstar) i coneixes el comportament per defecte davant d'un patró sense coincidències, que és la causa silenciosa de tants bucles trencats.
Amb això tanques les eines de manipulació de fitxers del mòdul. Les cerques per criteris que un patró de nom no pot expressar —data, mida, permisos, profunditat— són territori de find, a 05-01.
Queda una última peça, i és purament de productivitat. A la lliçó 02-06 aprendràs a moure't per la terminal a la velocitat d'un professional: reutilitzar ordres de l'historial, buscar cap enrere amb Ctrl-R, editar la línia sense fletxes i automatitzar el teu dia a dia amb àlies. És la lliçó que tanca el mòdul i et deixa a punt per fer el salt de la terminal a l'script.
Curs de Programació en Bash
Mòdul 1: Introducció a Bash
- Què és Bash?
- Configurar el teu Entorn
- Navegació Bàsica per la Línia d'Ordres
- Entendre el Shell
- Trobar Ajuda: man, help i --help
Mòdul 2: Ordres Bàsiques de Bash
- Operacions amb Fitxers i Directoris
- Ordres de Processament de Text
- Permisos i Propietat dels Fitxers
- Redirecció i Canonades
- Comodins i Expansió de Rutes
- Historial i Dreceres de Teclat
Mòdul 3: Fonaments de Scripting
- Crear i Executar un Script
- Variables i Constants
- Operadors Bàsics
- Sentències Condicionals
- Arguments i Entrada de l'Usuari
- Cometes, Expansió i Substitució
Mòdul 4: Scripting Intermedi
- Bucles en Bash
- Funcions en Bash
- Arrays i Arrays Associatius
- Manipulació de Cadenes
- La Sentència case i els Menús Interactius
- Aritmètica i Càlculs Numèrics
Mòdul 5: Tècniques Avançades de Scripting
- Operacions Avançades amb Fitxers
- Gestió de Processos
- Gestió d'Errors i Depuració
- Expressions Regulars
- Entrada/Sortida Avançada: Descriptors i Here-Documents
- Scripts Modulars i Llibreries Reutilitzables
Mòdul 6: Treballar amb Eines Externes
Mòdul 7: Automatització i Programació
- Tasques Cron
- Automatitzar Tasques
- Scripts de Còpia i Restauració
- Monitoratge i Registre
- Serveis i Temporitzadors amb systemd
- Automatització Remota amb SSH
Mòdul 8: Bones Pràctiques i Optimització
- Escriure Codi Llegible
- Optimitzar Scripts en Bash
- Consideracions de Seguretat
- Control de Versions amb Git
- Anàlisi Estàtica amb ShellCheck i shfmt
- Proves Automatitzades amb Bats
- Portabilitat: POSIX sh enfront de Bashismes
