bash
foi inicialmente projetado no final dos anos 80 como um clone parcial de ksh
com alguns recursos interativos do csh / tcsh.
As origens do globbing têm que ser encontradas nas primeiras conchas que ele constrói.
ksh
em si é uma extensão do shell Bourne. A própria shell Bourne (lançada em 1979 no Unix V7) foi uma implementação limpa do zero, mas não partiu completamente do shell Thompson (o shell do V1 - > V6) e dos recursos incorporados do shell Mashey.
Em particular, argumentos de comando ainda eram separados por espaços em branco, |
era agora o operador new pipe, mas ^
ainda era suportado como uma alternativa (e também explica por que você usa [!a-z]
e não [^a-z]
) $1
ainda era o primeiro argumento para um script e a barra invertida ainda era o caractere de escape. Muitos dos operadores regexp ( ^\|$
) têm um significado especial próprio no shell.
O Thompson contava com um utilitário externo para globbing. Quando sh
não encontrou *
, [
ou ?
s no comando, ele executaria o comando através de glob
.
rm *.txt
acabaria executando o glob como:
["glob", "rm", "*.txt"]
e glob acabariam executando rm
com a lista de arquivos correspondentes a esse padrão.
grep a.\*b *.txt
executaria glob
como:
["glob", "grep", "a.2b", "*.txt"]
O *
acima foi citado definindo o 8º bit nesse caractere, evitando que glob
o trate como curinga. glob
então removeria esse bit antes de chamar grep
.
Para fazer o equivalente com regexps, isso seria:
regexp rm '\.txt$'
Ou:
regexp rm '^[^.].*\.txt$'
para excluir arquivos de pontos.
A necessidade de escapar dos operadores à medida que eles duplicam como caracteres especiais de shell, o fato de .
, comum em nomes de arquivos ser um operador regexp, não torna muito apropriado combinar nomes de arquivos e complicado para um iniciante. Na maioria dos casos, tudo o que você precisa são curingas que possam substituir um ( ?
) ou qualquer número ( *
) de caracteres.
Agora, diferentes shells adicionaram diferentes operadores globbing. Atualmente, os ksh e zsh globs (e até certo ponto bash -O extglob
que implementam um subconjunto de ksh globs) são funcionalmente equivalentes aos regexps com uma sintaxe que é menos complicada de usar com nomes de arquivos e a sintaxe atual do shell. Por exemplo, em zsh
(com extensão extendedglob), você pode fazer:
echo a#.txt
se você quiser (improvável) para combinar nomes de arquivos que consistem em sequências de a
seguidas por .txt
. Mais fácil que echo (^a*\.txt$)
(aqui usando chaves como uma maneira de isolar os operadores regex dos operadores de shell, que poderiam ter sido uma maneira que os shells pudessem lidar com isso).
echo (foo|bar|<1-20>).(#i)mpg
Para arquivos mpg (sem distinção entre maiúsculas e minúsculas) cujo nome de base é foo, bar ou um número decimal de 1 a 20 ...
ksh93
agora também pode incorporar expressões regulares (básicas, estendidas, semelhantes a perl ou "aumentadas") em seus globs (embora seja bastante bugs) e até fornece uma ferramenta para converter entre glob e regexp ( printf %R
, printf %P
):
echo ~(Ei:.*\.txt)
para corresponder arquivos txt (não ocultos) com E expressões regulares xtended, caso i sem sensibilidade.