Я ожидал не получить никакого вывода.
Если бы nullglob
они использовались по умолчанию, многие команды вели бы себя совершенно неожиданно, потому что, как правило (к сожалению), команды обрабатывают случай нулевых аргументов имени файла качественно иным образом, чем один или несколько аргументов имени файла.
Предположим, что вы включили nullglob
( shopt -s nullglob
), и вы находитесь в каталоге, где не найдено ни одного файла *.txt
. Тогда *.txt
действительно расширится до нуля - не пустое поле, а вообще никаких полей - как вы и ожидали. Но это будет иметь следующие результаты:
ls *.txt
будет перечислять все файлы в текущем каталоге (кроме скрытых файлов), потому что это то, что ls
происходит, когда вы не передаете ему аргументы имени файла.
cat *.txt
будет читать со стандартного ввода , потому что, когда cat
нет аргументов имени файла, это как если бы вы работали cat -
. Если он работает в интерактивном режиме, он сидит в ожидании ввода. Многие команды ведут себя таким образом.
cp *.txt dest/
потерпит неудачу с ошибкой cp: missing destination file operand after 'dest/'
. Это не катастрофа, но это сбивает с толку и весьма отличается от молчаливого успеха, который, вероятно, желателен.
file *.txt
и различные другие программы, не имеющие специального поведения для случая нулевых аргументов имени файла, все равно будут с ошибкой или сообщением об использовании, если ни одна из них не будет передана.
- Даже случаи, которые интуитивно чувствуют, что они должны работать часто, не будут.
printf 'Got file: "%s"\n' *.txt
будет печатать Got file: ""
вместо ничего.
- Случайное отказ процитировать вхождения
*
, ?
и [
что не предполагается расширить оболочку бы чаще производить очевидно неправильные результаты, но таким образом , что может быть трудно понять. Например, если имена файлов в текущем каталоге не начинаются gedit
, то apt list gedit*
(где это apt list 'gedit*'
было задумано) станет просто apt list
и перечислит все доступные пакеты.
Так что хорошо, что вы не получаете такое поведение, не запрашивая его. Вероятно, наиболее распространенной практической ситуацией, которая на самом деле упрощается, nullglob
является for f in *.txt
. Смотрите также этот вопрос (с которым связался ответ Сергея Колодяжного ).
Сложнее ответить на вопрос, почему failglob
- если ошибка расширения, связанная с тем, что глобус не соответствует ни одному файлу, - не используется по умолчанию в bash. Я считаю, что ответ Сергея Колодяжного фиксирует причину этого, даже не обращаясь к нему напрямую. Сохранение нерасширяющихся глобусов без возникновения ошибки расширения является (возможно, к сожалению) стандартизированным поведением, а также традиционным и, следовательно, ожидаемым поведением. Хотя bash не пытается быть полностью POSIX-совместимым, если он не вызывается с именем sh
или не передается --posix
опция, многие из его вариантов разработки, даже когда не в режиме POSIX, следуют непосредственно за POSIX. Им пришлось выбрать какое-то поведение, и есть недостатки, связанные с несоответствием ожиданиям пользователей.
Я думаю, что это наименее исторически влиятельный аспект этого вопроса, поэтому я сохранил его напоследок ... но стоит упомянуть, что в nullglob
поведении есть что-то немного странно концептуальное .
nullglob
на первый взгляд кажется элегантным, поскольку синтаксически он рассматривает случай совпадения файлов с нулями ничем не иначе, как случай с одним, двумя или любым другим числом. Команды, которые мы запускаем, для которых глобусы расширяются в аргументы, не склонны рассматривать их одинаково, как подробно описано выше. Но синтаксически это, по крайней мере, кажется правильным, и я думаю, что это мотивация для вашего вопроса.
И, тем не менее, есть еще одно, более тонкое несоответствие, которое nullglob
не устраняется - оно на самом деле усиливается. Случай с нулевыми символами глобинга («подстановочные знаки») трактуется совершенно иначе, чем случай с одним, двумя или любым другим числом. Например, с помощью shopt -s nullglob
, если ab?d?f
файлы не совпадают, они удаляются; если ab?d
файлы не совпадают, они удаляются; но если ab
не совпадает ни с одним файлом (то есть, если нет файла, имя которого точно ab
), он все равно не удаляется. Конечно, это будет катастрофа, если она будет удалена, потому что она может вообще не ссылаться на существующий файл в текущем каталоге; это может даже не ссылаться на файл. Но это все еще устраняет любую надежду на полную последовательность.
Три поведения, которые предоставляет bash - по умолчанию обработка глобусов, которые не соответствуют ни одному из файлов, как если бы они не были глобусами, и передача их нерасширенными, поведение, которое вы ожидали от них (если вы простите этот странный поворот фразы) как означающий все нули файлов, которые соответствуют match ( nullglob
), и безопасное поведение, учитывающее их ошибки ( failglob
) - все они представляют разные подходы к неоднозначности, присущей оболочке, и не могут знать, предназначено ли какое-либо конкретное слово быть имя файла. Оболочка выполняет свои расширения без знания того, как конкретные команды, которые вы вызываете с ней, будут обрабатывать свои аргументы.
Это один из многих случаев разделения интересов . В системах, дизайн которых соответствует философии Unix, каждая часть предназначена для того, чтобы делать что-то одно и делать это хорошо . Оболочка обрабатывает текст в команды и аргументы и вызывает те команды, большинство из которых являются внешними по отношению к самой оболочке. Это, как правило, намного приятнее и гибче, чем системы, в которых внешние команды сами отвечают за выполнение этих преобразований (как в случае традиционных командных процессоров в DOS и Windows). Но у этого есть свои случайные недостатки.
shopt -s nullglob
выдаст пустые строки для несопоставленных шаблонов иshopt -u nullglob
(стандартная настройка) выдаст сам шаблон.