Mude para o Bourne Again Shell ( /bin/bash
) do Bourne Shell ( /bin/sh
), e uma solução simples se torna possível.
A página bash(1)
man menciona a opção nullglob :
If set, bash allows patterns which match no files (see Pathname Expansion above) to expand to a null string, rather than themselves.
A seção Expansão do nome do caminho diz:
After word splitting, …bash scans each word for the characters *, ?, and [. If one of these characters appears, then the word is regarded as a pattern, and replaced with an alphabetically sorted list of file names matching the pattern. If no matching file names are found, and the shell option nullglob is not enabled, the word is left unchanged. If the nullglob option is set, and no matches are found, the word is removed.…
Portanto, a configuração da opção nullglob fornece o comportamento desejado para os padrões. Se nenhum arquivo corresponder ao padrão, o loop não será executado.
#!/bin/bash
shopt -s nullglob
for f in *.ext; do
handle "$f"
done
Mas a opção nullglob pode interferir no comportamento desejado de outros comandos. Assim, você provavelmente achará melhor salvar a configuração existente de nullglob e restaurá-la depois. Felizmente, o comando shopt -p
builtin emite a saída em um formato que pode ser reutilizado como entrada. Mas emite saída para todas as opções, então use grep
para escolher a configuração nullobj . Veja o log abaixo (onde $
indica o prompt de comando do bash):
$ shopt -p | grep nullglob
shopt -u nullglob
$ shopt -s nullglob
$ shopt -p | grep nullglob
shopt -s nullglob
Assim, a sintaxe final do bash para lidar com zero ou mais arquivos correspondentes a um padrão curinga é semelhante a:
#!/bin/bash
SAVED_NULLGLOB=$(shopt -p | grep nullglob)
shopt -s nullglob
for f in *.ext; do
handle "$f"
done
eval "$SAVED_NULLGLOB"
Além disso, a questão mencionou vários padrões, como:
for f in *.ext1 special.ext1 *.ext2; do ...
A opção nullglob não afeta uma palavra na lista que não seja "padrão", por isso special.ext1
ainda será passado para o loop. A única solução para isso é @Gordon Davisson continue
expression, [ -e "$f" ] || continue
.
Reconhecimento: ambos @Ignacio Vazquez-Abrams e @ Gordon Davisson aludiu à opção bash(1)
e seu nullglob . Obrigado. Uma vez que eles não contribuíram imediatamente com uma resposta com um exemplo totalmente trabalhado, eu estou fazendo isso sozinho.