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