[ -f /*.txt ]
retornará true somente se houver um (e apenas um) arquivo não oculto em /
cujo nome termina .txt
e se esse arquivo for um arquivo regular ou um link simbólico para um arquivo regular.
Isso ocorre porque os curingas são expandidos pelo shell antes de serem passados para o comando (aqui [
).
Portanto, se há um /a.txt
e /b.txt
, [
serão passados 5 argumentos: [
, -f
, /a.txt
, /b.txt
e ]
. [
reclamaria que -f
é dado muitos argumentos.
Se você deseja verificar se o *.txt
padrão se expande para pelo menos um arquivo não oculto (regular ou não):
shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"
shopt -s nullglob
é bash
específico, mas escudos como ksh93
, zsh
, yash
, tcsh
tem declarações equivalentes.
Observe que ele encontra esses arquivos lendo o conteúdo do diretório; ele não tenta acessar esses arquivos, o que o torna mais eficiente do que soluções que chamam comandos como ls
ou stat
nessa lista de arquivos computados pelo shell.
O sh
equivalente padrão seria:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "$@"
esac
O problema é que, com os shells Bourne ou POSIX, se um padrão não corresponde, ele se expande. Portanto, se *.txt
expandir *.txt
, você não sabe se é porque não há .txt
arquivo no diretório ou porque existe um arquivo chamado *.txt
. Usando[*].txt *.txt
permite discriminar entre os dois.
/
? Além disso, falta um ponto e vírgula antesfi
.