nullglob
Вариант (который кстати является zsh
изобретением, только добавил года спустя bash
( 2.0
)) , не было бы идеальными в ряде случаев. И ls
хороший пример:
ls *.txt
Или его более правильный эквивалент:
ls -- *.txt
С nullglob
on будет работать ls
без аргумента, который рассматривается как ls -- .
(перечислить текущий каталог), если не найдено ни одного файла, что, вероятно, хуже, чем вызов ls
с литералом в *.txt
качестве аргумента.
У вас будут похожие проблемы с большинством текстовых утилит:
grep foo *.txt
Будет искать foo
на стандартный ввод, если нет txt
файла.
Более разумное значение по умолчанию - csh, tcsh, zsh или fish 2.3+ (и ранних оболочек Unix) - вообще отменить команду, если глобус не совпадает.
bash
(начиная с версии 3) имеет failglob
опции для этого (интересно к этой дискуссии, так как вопреки ash
, AT & T ksh
или zsh
, bash
не поддерживает локальные области для вариантов (хотя это изменить в 4.4), что вариант , когда включен глобально делает перерыв несколько вещей как функции завершения bash).
Обратите внимание , что CSH и Tcsh немного отличается от zsh
, fish
или bash -O failglob
в таких случаях , как:
ls -- *.txt *.html
Где вам нужно, чтобы все шарики не совпадали, чтобы команда была отменена. Например, если есть один текстовый файл и нет HTML-файла, это становится:
ls -- file.txt
Вы можете получить такое поведение с zsh
помощью, setopt cshnullglob
хотя более разумный способ сделать это zsh
- использовать глобус вроде:
ls -- *.(txt|html)
В zsh
and ksh93
вы также можете применять nullglob для каждого отдельного глобуса, что намного более разумно, чем изменение глобального параметра:
files=(*.txt(N)) # zsh
files=(~(N)*.txt) # ksh93
создаст пустой массив, если нет 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
содержит подстановочные знаки (это больше похоже на расширение макроса препроцессора). там же, как и в расширенном значении, снова был разобран код оболочки)).
Неудачные глобусы, которые не совпадают, означают, например, что:
pattern='a.*b'
grep $pattern file
не выполнит команду (если a.whateverb
в текущем каталоге нет файлов). csh
(который также выполняет подстановку при расширении переменной) в этом случае не выполняет команду (и я бы сказал, что это лучше, чем оставлять там бездействующую ошибку, даже если это не так хорошо, как вообще не делать подстановку, как в zsh
).