Я играл с расширением, и я заметил своеобразное поведение. Я попытался сделать:
echo ./*.txt
И у меня не было никакого файла .txt в моем текущем каталоге. Вывод, который я получил, был:
./*.txt
Мне просто любопытно: почему я это получил? Я ожидал не получить никакого вывода.
PS: Когда у меня был файл .txt
, расширение было правильно интерпретировано. Другими словами, скажем, у меня есть файл, smthn.txt
, эхо фактически повторяется current_directory/smthn.txt
.
Адаптация от удара окружает страницу справочника,
колотите сканирует каждое слово для символов *?, и [. Если один из этих символов появляется, то слово рассматривается как шаблон и заменяется в алфавитном порядке отсортированным списком имен файлов, соответствующих шаблону. Если никакие имена файлов соответствия не найдены, и опция оболочки nullglob не включена, слово оставлено без изменений. Если nullglob опция установлена, и никакие соответствия не найдены, слово удалено.
В этом случае я предполагаю, что nullglob не включен, таким образом, слово оставлено без изменений - следовательно вывод, Вы видите.
Я ожидал не получать любой вывод.
Если 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
. См. также этот вопрос (который ответ Sergiy Kolodyazhnyy, связанный с).
Более трудный вопрос ответить состоит в том почему failglob
- то, где это - ошибка расширения иметь шарик, который не соответствует никаким файлам - не является значением по умолчанию в ударе. Я полагаю, что ответ Sergiy Kolodyazhnyy получает причину этого даже, не обращаясь к нему непосредственно. Сохранение нерасширяющихся шариков, не производя ошибку расширения является (возможно, к сожалению) стандартизированным поведением, и это также традиционно, и таким образом ожидаемое, поведение. Хотя удар не пытается быть полностью совместимым POSIX, если он не вызывается с именем sh
или передал --posix
опция, многие ее проектные решения, даже когда не в POSIX режим следуют за POSIX непосредственно. Они должны были выбрать некоторое поведение, и существуют оборотные стороны, связанные с хождением вразрез с ожиданиями пользователей.
Я думаю, что это - наименее исторически влиятельный аспект вопроса, таким образом, я сохранил его для последнего..., но стоит упомянуть, что существует что-то немного концептуально нечетное о nullglob
поведение.
nullglob
кажется изящным сначала, потому что, синтаксически, это рассматривает случай нулевых файлов соответствия не по-другому по сравнению со случаем один, два, или любое другое число. Команды, которые мы выполняем, в пользу которого шарики расширяются в аргументы, не имеют тенденцию рассматривать их то же, как детализировано выше. Но синтаксически это, по крайней мере, чувствует себя хорошо, который я думаю, мотивация для Вашего вопроса.
И все же, существует другой, более тонкое несоответствие это nullglob
не обращается - что это на самом деле усиливает. Случай нуля globbing символы ("подстановочные знаки") рассматривают глубоко по-другому по сравнению со случаем одного, или два, или любое другое число. Например, с shopt -s nullglob
, если ab?d?f
не соответствует никаким файлам, это удалено; если ab?d
не соответствует никаким файлам, это удалено; но если ab
не соответствует никаким файлам (т.е. если нет никакого файла, имя которого точно ab
) это все еще не удалено. Конечно, это была бы авария, если бы это было удалено, потому что это не могло бы быть предназначено для обращения к существующему файлу в текущем каталоге вообще; это даже не могло бы относиться к файлу. Но это все еще устраняет любую надежду на общую непротиворечивость.
Эти три удара поведений обеспечивают - значение по умолчанию обработки шариков, которые не соответствуют никаким файлам, как будто они не были шариками и передачей их нерасширенный, поведение, которое Вы ожидали обработки их (при прощении этого нечетного оборота речи) как показывающий весь нуль файлов, которые действительно соответствуют (nullglob
), и безопасное поведение рассмотрения их ошибки (failglob
) - все представляют разные подходы к неоднозначности, свойственной от оболочки, не бывшей способной знать, предназначается ли какое-либо конкретное слово, чтобы быть именем файла. Оболочка выполняет свои расширения без ведома того, как конкретные команды, которые Вы называете с ним, будут рассматривать свои аргументы.
Это - один из многих экземпляров разделения проблем. В системах, дизайн которых следует за философией Unix, каждая часть предназначается, чтобы сделать одну вещь и сделать это хорошо. Оболочка обрабатывает текст в команды и аргументы и вызывает те команды, большинство которых является внешним к самой оболочке. Это имеет тенденцию быть намного более хорошим и более универсальным, чем системы, где внешние команды самостоятельно ответственны за выполнение тех преобразований (как с традиционными командными процессорами в DOS и Windows). Но это имеет свои случайные оборотные стороны.
Главная причина состоит в том, потому что это - стандартное поведение, указанное POSIX - стандарт, который касается командного языка оболочки и среди прочего сопоставления с образцом (оболочки такой как bash
, dash
оболочка - значение по умолчанию Ubuntu /bin/sh
, и ksh
следуйте этому стандарту). От раздела 2.13.3 Шаблонов, Используемых для Расширения Имени файла:
Если шаблон не будет соответствовать никаким существующим именам файлов или путям, то строка образца должна быть оставлена без изменений.
Это, конечно, имеет побочный эффект - соответствие имени файла, которое может быть буквально *.txt
. nullglob
опция в bash
и zsh
может помочь: если через ту опцию включают shopt -s nullglob
(и это не включено по умолчанию, который относится к этому вопросу), затем globstar будет расширен до пустой строки, когда никакие имена файлов соответствия не нашли. ksh93
имеет его собственный усовершенствованный механизм сопоставления с образцом, который достигает того же эффекта ~(N)*.txt
См. также, Почему nullglob не является значением по умолчанию?