bash
è stato inizialmente progettato alla fine degli anni '80 come un clone parziale di ksh
con alcune funzionalità interattive di csh / tcsh.
Le origini del globbing devono essere trovate in quelle precedenti conchiglie su cui si basa.
ksh
di per sé è un'estensione della shell Bourne. La stessa shell Bourne (rilasciata per la prima volta nel 1979 in Unix V7) era un'implementazione pulita da zero, ma non si discostava completamente dalla shell Thompson (la shell di V1 -> V6) e incorporava funzionalità della shell Mashey.
In particolare, gli argomenti di comando erano ancora separati da spazi, |
ora era il nuovo operatore pipe ma ^
era ancora supportato come alternativa (e spiega anche perché lo fai [!a-z]
e non [^a-z]
), $1
era ancora il primo argomento di uno script e la barra rovesciata era ancora il carattere di escape . Quindi molti operatori regexp ( ^\|$
) hanno un significato speciale nella shell.
La shell Thompson si basava su un'utilità esterna per il globbing. Se sh
trovato non quotato *
, [
o ?
s nel comando, eseguirà il comando attraverso glob
.
rm *.txt
finirebbe per girare glob come:
["glob", "rm", "*.txt"]
e glob sarebbe finito rm
con l'elenco dei file corrispondenti a quel modello.
grep a.\*b *.txt
sarebbe eseguito glob
come:
["glob", "grep", "a.\252b", "*.txt"]
Quanto *
sopra è stato citato impostando l'ottavo bit su quel personaggio, impedendo glob
di trattarlo come un jolly. glob
rimuoverebbe quel bit prima di chiamare grep
.
Per fare l'equivalente con regexps, sarebbe stato:
regexp rm '\.txt$'
O:
regexp rm '^[^.].*\.txt$'
per escludere file dot.
La necessità di sfuggire agli operatori mentre si raddoppiano come caratteri speciali della shell, il fatto che .
, comune nei nomi dei file sia un operatore regexp, non è molto appropriato per abbinare i nomi dei file e complicato per un principiante. Nella maggior parte dei casi, tutto ciò che serve sono i caratteri jolly che possono sostituire uno ( ?
) o qualsiasi numero ( *
) di caratteri.
Ora, conchiglie diverse hanno aggiunto diversi operatori globbing. Al giorno d'oggi, i globs ksh e zsh (e in una certa misura bash -O extglob
che implementano un sottoinsieme di globi ksh) sono funzionalmente equivalenti a regexps con una sintassi che è meno ingombrante da usare con i nomi dei file e l'attuale sintassi della shell. Ad esempio, in zsh
(con estensione extendedglob), puoi fare:
echo a#.txt
se si desidera (improbabile) corrispondere a nomi di file costituiti da sequenze a
seguite da .txt
. Più facile di echo (^a*\.txt$)
(qui usando le parentesi graffe come un modo per isolare gli operatori regex dagli operatori di shell che avrebbero potuto essere un modo in cui le shell potevano gestirlo).
echo (foo|bar|<1-20>).(#i)mpg
Per file mpg (senza distinzione tra maiuscole e minuscole) il cui nome base è pippo, barra o un numero decimale compreso tra 1 e 20 ...
ksh93
ora può anche incorporare regexps (base, estesa, perl-like o "aumentata") nei suoi globs (anche se è piuttosto buggy) e persino fornire uno strumento per convertire tra glob e regexp ( printf %R
, printf %P
):
echo ~(Ei:.*\.txt)
a partita (non nascosto) file txt con E Xtended le espressioni regolari, tra maiuscole i nsensitively.
rm -- ^[^.].*\.txt$
invece dirm -- *.txt
?