В большинстве оболочек nullglob
не по умолчанию. Это означает, например, если вы запустите эту команду
ls *
в пустом каталоге он расширит *
глобус до литерала *
, а не до пустого списка аргументов. Существуют способы изменить это поведение, чтобы *
в пустом каталоге возвращался пустой список аргументов, который казался бы более интуитивным.
Итак, есть ли причина, по которой nullglob
отключено по умолчанию? Если так, то в чем причина?
*
это глобус и распространяется на все существующие файлы; как это «интуитивно» для особого случая, когда пустые глобусы каталогов «расширяются» до литерала*
?Ответы:
nullglob
Вариант (который кстати являетсяzsh
изобретением, только добавил года спустяbash
(2.0
)) , не было бы идеальными в ряде случаев. Иls
хороший пример:Или его более правильный эквивалент:
С
nullglob
on будет работатьls
без аргумента, который рассматривается какls -- .
(перечислить текущий каталог), если не найдено ни одного файла, что, вероятно, хуже, чем вызовls
с литералом в*.txt
качестве аргумента.У вас будут похожие проблемы с большинством текстовых утилит:
Будет искать
foo
на стандартный ввод, если нетtxt
файла.Более разумное значение по умолчанию - csh, tcsh, zsh или fish 2.3+ (и ранних оболочек Unix) - вообще отменить команду, если глобус не совпадает.
bash
(начиная с версии 3) имеетfailglob
опции для этого (интересно к этой дискуссии, так как вопрекиash
, AT & Tksh
илиzsh
,bash
не поддерживает локальные области для вариантов (хотя это изменить в 4.4), что вариант , когда включен глобально делает перерыв несколько вещей как функции завершения bash).Обратите внимание , что CSH и Tcsh немного отличается от
zsh
,fish
илиbash -O failglob
в таких случаях , как:Где вам нужно, чтобы все шарики не совпадали, чтобы команда была отменена. Например, если есть один текстовый файл и нет HTML-файла, это становится:
Вы можете получить такое поведение с
zsh
помощью,setopt cshnullglob
хотя более разумный способ сделать этоzsh
- использовать глобус вроде:В
zsh
andksh93
вы также можете применять nullglob для каждого отдельного глобуса, что намного более разумно, чем изменение глобального параметра:создаст пустой массив, если нет
txt
файла, вместо сбоя команды с ошибкой (или создания массива с одним*.txt
литеральным аргументом с другими оболочками).Версии
fish
до 2.3 работали бы как,bash -O nullglob
но выдают предупреждение, когда интерактивен, когда у шарика нет соответствия. Начиная с 2.3, он работает какzsh
за исключением глобусов, используемых вfor
,set
илиcount
.Теперь, на заметку истории, поведение было фактически нарушено оболочкой Борна. В предыдущих версиях Unix глобирование выполнялось через
/etc/glob
помощника, и этот помощник вел себя такcsh
: команда не выполнит команду, если ни один из глобусов не соответствует ни одному файлу, и удалит глобусы без совпадения в противном случае.Таким образом, ситуация, в которой мы находимся сегодня, связана с неправильным решением, принятым в оболочке Bourne.
Обратите внимание, что оболочка Bourne (и оболочка C) поставляется с еще одной новой функцией Unix: средой. Это означало , что переменная расширение (это предшественник только имел
$1
,$2
... позиционные параметры). Оболочка Bourne также ввела подстановку команд.Еще одно неудачное решение для оболочки Bourne заключалось в том, чтобы выполнить сглаживание (и разбиение) при расширении переменных и подстановке команд (возможно, для обратной совместимости с оболочкой Томпсона, где
echo $1
все равно будет выполняться вызов,/etc/glob
если он$1
содержит подстановочные знаки (это больше похоже на расширение макроса препроцессора). там же, как и в расширенном значении, снова был разобран код оболочки)).Неудачные глобусы, которые не совпадают, означают, например, что:
не выполнит команду (если
a.whateverb
в текущем каталоге нет файлов).csh
(который также выполняет подстановку при расширении переменной) в этом случае не выполняет команду (и я бы сказал, что это лучше, чем оставлять там бездействующую ошибку, даже если это не так хорошо, как вообще не делать подстановку, как вzsh
).источник
nullglob
кажется, что она нарушает завершение табуляции (нажатие клавиши табуляции ничего не делает, когда она включена).files=$(shopt -s nullglob;echo *.txt)
xpg_echo
) в скалярные переменные. Вы должны были бы что - то подобноеreadarray -td '' files < <(shopt -s nullglob; printf '%s\0' *.txt)
сbash
4.4 или выше , или(shopt -s nullglob; printf '%s\0' *.txt) | xargs -r0 cmd
с GNUxargs
для того , чтобы можно было использовать на все с произвольными именами файлов. Или, все еще с bash4.4, используйте вспомогательную функцию, которая используетlocal -
(скопированный из пепла 25 лет спустя) для локальной области действия для вариантов.