Por que o nullglob não é padrão?

50

Na maioria dos shells, o nullglob não é o padrão. Isso significa, por exemplo, se você executar este comando

ls *

em um diretório vazio, ele expandirá o * glob para um literal * , em vez de uma lista vazia de argumentos. Existem maneiras de mudar esse comportamento, de modo que * em um diretório vazio retornará uma lista vazia de argumentos, o que pareceria mais intuitivo.

Portanto, há uma razão pela qual nullglob está desativado por padrão? Se sim, qual é esse motivo?

    
por Dakkaron 21.05.2015 / 14:00

1 resposta

64

A opção nullglob (que BTW é uma invenção zsh , adicionada anos depois a bash ( 2.0 )) não seria ideal em vários casos. E ls é um bom exemplo:

ls *.txt

Ou o seu equivalente mais correto:

ls -- *.txt

Com nullglob on, executar ls sem nenhum argumento tratado como ls -- . (listar o diretório atual) se nenhum arquivo corresponder, o que provavelmente é pior do que chamar ls com um literal *.txt como argumento.

Você teria problemas semelhantes com a maioria dos utilitários de texto:

grep foo *.txt

Procuraria foo no stdin se não houver arquivo txt .

Um padrão mais sensato, e o de csh, tcsh, zsh ou fish 2.3+ (e de shells iniciais do Unix) é cancelar o comando se o glob não corresponder.

bash (desde a versão 3) tem uma opção failglob para isso (interessante para esta discussão, pois ao contrário de ash , AT & T ksh ou zsh , bash não suporta Escopos locais para opções (embora isso mude em 4.4), essa opção, quando ativada globalmente, quebra algumas coisas, como as funções de conclusão do bash).

Observe que csh e tcsh são um pouco diferentes de zsh , fish ou bash -O failglob em casos como:

ls -- *.txt *.html

Onde você precisa que todos os globs não correspondam para que o comando seja cancelado. Por exemplo, se houver um arquivo txt e nenhum arquivo html, isso se torna:

ls -- file.txt

Você pode obter esse comportamento com zsh com setopt cshnullglob , embora uma maneira mais sensata de fazer isso em zsh seria usar um glob como:

ls -- *.(txt|html)

Em zsh , você também pode aplicar nullglob em uma base por glob, que é uma abordagem muito melhor do que modificar uma configuração global:

files=(*.txt(N))

criaria uma matriz vazia se não houver nenhum arquivo txt em vez de falhar o comando com um erro (ou torná-lo uma matriz com um argumento *.txt literal com outros shells).

As versões de fish anteriores a 2.3 funcionariam como bash -O nullglob , mas emitiriam um aviso quando interativas quando uma glob não tivesse correspondência. Desde o 2.3, ele funciona como zsh , exceto para globs usados em for , set ou count .

Agora, na nota de histórico, o comportamento foi realmente quebrado pela shell Bourne. Nas versões anteriores do Unix, o globbing era feito através do /etc/glob helper e esse ajudante se comportava como csh : ele falharia o comando se nenhum dos globs correspondesse a nenhum arquivo e removeria os globs sem nenhuma correspondência.

Então, a situação em que estamos hoje é devido a uma má decisão tomada no shell Bourne.

Observe que o shell Bourne (e o shell C) veio com outro novo recurso Unix: o ambiente. Isso significava expansão variável (seu antecessor tinha apenas os parâmetros $1 , $2 ... posicionais). O shell Bourne também introduziu a substituição de comandos.

Outra falha na decisão de design do shell Bourne era realizar globbing (e divisão) na expansão de variáveis e na substituição de comando (possivelmente para compatibilidade com o shell Thompson, em que echo $1 ainda invocaria /etc/glob if $1 continham curingas (era mais parecido com uma expansão de macro pré-processador, como no valor expandido foi analisado novamente como código de shell)).

Globs com falha que não correspondem significaria, por exemplo, que:

pattern='a.*b'
grep $pattern file

falharia o comando (a menos que haja alguns arquivos a.whateverb no diretório atual). csh (que também executa globbing na expansão de variáveis) falha o comando nesse caso (e eu diria que é melhor do que deixar um erro inativo lá, mesmo que não seja tão bom quanto não fazer globbing como em zsh ).

    
por 22.05.2015 / 00:32