Eu estava brincando com a expansão e notei um comportamento peculiar. Eu tentei fazer:
echo ./*.txt
E eu não tinha nenhum arquivo .txt no meu diretório atual. A saída que obtive foi:
./*.txt
Só estou curioso: por que eu consegui isso? Eu esperava não obter nenhuma saída.
PS: Quando eu tinha um .txt
arquivo, a expansão foi corretamente interpretada. Em outras palavras, digamos que eu tinha um arquivo smthn.txt
, o eco realmente ecoou current_directory/smthn.txt
.
fonte
shopt -s nullglob
produzirá cadeias vazias para padrões sem correspondência eshopt -u nullglob
(configuração padrão) produzirá o próprio padrão.Se
nullglob
fosse o padrão, muitos comandos se comportariam inesperadamente, porque é (talvez infelizmente) comum que os comandos tratem o caso de zero argumentos de nome de arquivo de uma maneira qualitativamente diferente do que o caso de um ou mais argumentos de nome de arquivo.Suponha que você tenha ativado
nullglob
(shopt -s nullglob
) e esteja em um diretório onde nenhum arquivo corresponde*.txt
. Então,*.txt
ele realmente se expandirá para nada - não um campo vazio, mas nenhum campo - como você esperava. Mas isso teria esses resultados:ls *.txt
listaria todos os arquivos no diretório atual (exceto arquivos ocultos), porque é o quels
acontece quando você não passa nenhum argumento de nome de arquivo.cat *.txt
leria da entrada padrão , porque quandocat
não tem argumentos de nome de arquivo, é como se você tivesse executadocat -
. Se estiver executando interativamente, fica aguardando a entrada. Muitos comandos se comportam dessa maneira.cp *.txt dest/
falharia com o errocp: missing destination file operand after 'dest/'
. Isso não é um desastre, mas é confuso e bem diferente do sucesso silencioso que provavelmente é desejado.file *.txt
, e vários outros programas sem comportamento especial para o caso de zero argumentos de nome de arquivo, ainda falhariam com uma mensagem de erro ou uso quando nenhuma delas fosse passada.printf 'Got file: "%s"\n' *.txt
imprimiria emGot file: ""
vez de nada.*
,?
e[
que não pretendem ser expandidas pelo shell produziriam com mais frequência resultados obviamente errados, mas de maneiras que podem ser difíceis de descobrir. Por exemplo, se nenhum nome de arquivo no diretório atual fosse iniciadogedit
, entãoapt list gedit*
(ondeapt list 'gedit*'
pretendido) se tornaria justoapt list
e listaria todos os pacotes disponíveis.Portanto, é bom que você não tenha esse comportamento sem solicitá-lo. Provavelmente a situação prática mais comum que é realmente simplificada
nullglob
éfor f in *.txt
. Veja também esta pergunta (à qual a resposta de Sergiy Kolodyazhnyy está vinculada).A pergunta mais difícil de responder é por que -
failglob
onde é um erro de expansão ter um globo que não corresponde a nenhum arquivo - não é o padrão no bash. Acredito que a resposta de Sergiy Kolodyazhnyy capte a razão disso, mesmo sem abordá-la diretamente. Reter globs não expansíveis sem produzir um erro de expansão é (talvez infelizmente) o comportamento padronizado, e também é um comportamento tradicional e, portanto, esperado. Embora o bash não tente ser totalmente compatível com POSIX, a menos que seja chamado com o nomesh
ou tenha passado a--posix
opção, muitas de suas opções de design, mesmo quando não estão no modo POSIX, seguem o POSIX diretamente. Eles tiveram que escolher algum comportamento, e há desvantagens associadas a ir contra as expectativas dos usuários.Acho que esse é o aspecto menos influente do ponto de vista histórico, então guardei por último ... mas vale a pena mencionar que há algo um pouco conceitualmente estranho no
nullglob
comportamento.nullglob
parece elegante a princípio porque, sintaticamente , trata o caso de zero arquivos correspondentes de maneira diferente do caso de um, dois ou qualquer outro número. Os comandos que executamos, nos quais os globs se expandem para argumentos, não tendem a tratá-los da mesma forma, conforme detalhado acima. Mas sintaticamente isso pelo menos parece certo, o que eu acho que é a motivação para sua pergunta.E, no entanto, há outra inconsistência mais sutil que
nullglob
não trata - que ela realmente amplifica. O caso de zero caracteres " globbing " ("curingas") é tratado profundamente diferente do de um, dois ou qualquer outro número. Por exemplo, comshopt -s nullglob
, seab?d?f
não corresponder a nenhum arquivo, ele será removido; seab?d
não corresponder a nenhum arquivo, ele será removido; mas seab
não corresponder a nenhum arquivo (ou seja, se não houver um arquivo cujo nome seja exatamenteab
), ele ainda não será removido. Obviamente, seria um desastre se fosse removido, porque pode não ter a intenção de se referir a um arquivo existente no diretório atual; pode nem se referir a um arquivo. Mas isso ainda elimina qualquer esperança de consistência total.Os três comportamentos que o bash fornece - o padrão de tratar globs que não correspondem a nenhum arquivo como se eles não fossem globs e transmiti-los sem expansão, o comportamento que você esperava de tratá-los (se você perdoa essa estranha frase) como significando todo o zero dos arquivos que correspondem (
nullglob
) e o comportamento seguro de considerá-los erros (failglob
) - todos representam abordagens diferentes para a ambiguidade inerente ao shell, não sendo possível saber se alguma palavra em particular deve ser uma nome do arquivo. O shell executa suas expansões sem o conhecimento de como os comandos específicos que você chama com ele tratarão seus argumentos.Esse é um dos muitos casos de separação de preocupações . Em sistemas cujo design segue a filosofia do Unix, cada parte tem a intenção de fazer uma coisa e fazê-la bem . O shell processa o texto em comandos e argumentos e chama esses comandos, a maioria dos quais são externos ao próprio shell. Este tende a ser um agradável muito e mais versátil do que os sistemas onde os comandos externos são eles próprios responsáveis por executar essas transformações (como acontece com os processadores de comando tradicionais em DOS e Windows). Mas tem suas desvantagens ocasionais.
fonte
failglob
. Portanto, não pode ser o padrão porque nem sempre foi suportado.A principal razão é porque este é o comportamento padrão especificado pelo POSIX - o padrão que cobre desembolsar linguagem de comando e entre outras coisas padrão correspondentes (conchas tais como
bash
,dash
shell - padrão do Ubuntu/bin/sh
, eksh
seguem esse padrão). Na seção 2.13.3 Padrões usados para expansão de nome de arquivo :Obviamente, isso tem um efeito colateral - que corresponde ao nome do arquivo que pode ser literalmente
*.txt
. Anullglob
opçãobash
ezsh
pode ajudar: se essa opção estiver ativada viashopt -s nullglob
(e não estiver ativada por padrão, o que se aplica a esta pergunta), o globstar será expandido para uma string vazia quando nenhum nome de arquivo correspondente for encontrado.ksh93
possui seu próprio mecanismo avançado de correspondência de padrões, que obtém o mesmo efeito~(N)*.txt
Consulte também Por que o nullglob não é o padrão?
fonte