Расширение с помощью * .txt в оболочке не работает, если нет файла .txt

Я играл с расширением, и я заметил своеобразное поведение. Я попытался сделать:

echo ./*.txt

И у меня не было никакого файла .txt в моем текущем каталоге. Вывод, который я получил, был:

./*.txt

Мне просто любопытно: почему я это получил? Я ожидал не получить никакого вывода.

PS: Когда у меня был файл .txt, расширение было правильно интерпретировано. Другими словами, скажем, у меня есть файл, smthn.txt, эхо фактически повторяется current_directory/smthn.txt.

10
задан 9 August 2019 в 07:07

3 ответа

Адаптация от удара окружает страницу справочника,

колотите сканирует каждое слово для символов *?, и [. Если один из этих символов появляется, то слово рассматривается как шаблон и заменяется в алфавитном порядке отсортированным списком имен файлов, соответствующих шаблону. Если никакие имена файлов соответствия не найдены, и опция оболочки nullglob не включена, слово оставлено без изменений. Если nullglob опция установлена, и никакие соответствия не найдены, слово удалено.

В этом случае я предполагаю, что nullglob не включен, таким образом, слово оставлено без изменений - следовательно вывод, Вы видите.

15
ответ дан 23 November 2019 в 04:17

Я ожидал не получать любой вывод.

Если 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). Но это имеет свои случайные оборотные стороны.

13
ответ дан 23 November 2019 в 04:17

Главная причина состоит в том, потому что это - стандартное поведение, указанное POSIX - стандарт, который касается командного языка оболочки и среди прочего сопоставления с образцом (оболочки такой как bash, dash оболочка - значение по умолчанию Ubuntu /bin/sh, и ksh следуйте этому стандарту). От раздела 2.13.3 Шаблонов, Используемых для Расширения Имени файла:

Если шаблон не будет соответствовать никаким существующим именам файлов или путям, то строка образца должна быть оставлена без изменений.

Это, конечно, имеет побочный эффект - соответствие имени файла, которое может быть буквально *.txt. nullglob опция в bash и zsh может помочь: если через ту опцию включают shopt -s nullglob (и это не включено по умолчанию, который относится к этому вопросу), затем globstar будет расширен до пустой строки, когда никакие имена файлов соответствия не нашли. ksh93 имеет его собственный усовершенствованный механизм сопоставления с образцом, который достигает того же эффекта ~(N)*.txt

См. также, Почему nullglob не является значением по умолчанию?

6
ответ дан 23 November 2019 в 04:17

Другие вопросы по тегам:

Похожие вопросы: