[ -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.