[ -f /*.txt ]
вернет true, только если есть один (и только один) не скрытый файл, в /имени которого заканчивается имя, .txtи если этот файл является обычным файлом или символической ссылкой на обычный файл.
Это связано с тем, что подстановочные знаки раскрываются оболочкой перед передачей в команду (здесь [).
Так что, если есть /a.txtи /b.txt, [будут переданы 5 аргументов: [, -f, /a.txt, /b.txtи ]. [потом жаловался бы, что -fдано слишком много аргументов.
Если вы хотите убедиться, что *.txtшаблон расширяется хотя бы до одного скрытого файла (обычного или нет):
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конкретным, но скорлупа нравится ksh93, zsh, yash, tcshимеют эквивалентные высказывания.
Обратите внимание, что он находит эти файлы, читая содержимое каталога, он вообще не пытается получить доступ к этим файлам, что делает его более эффективным, чем решения, которые вызывают такие команды, как lsили statв этом списке файлов, вычисляемых оболочкой.
Стандартный shэквивалент будет:
set -- [*].txt *.txt
case "$1$2" in
('[*].txt*.txt') ;;
(*) shift; script "$@"
esac
Проблема в том, что с оболочками Bourne или POSIX, если шаблон не совпадает, он расширяется до самого себя. Так что, если *.txtрасширится до *.txt, вы не знаете, будет ли это потому, что в .txtкаталоге нет файла или потому что есть один названный файл *.txt. Использование [*].txt *.txtпозволяет различать два.
/? Кроме того, вы пропустите точку с запятой раньшеfi.