Рассмотрим два образца оболочки
$ ls
myDoc.html
SomeDirectory
someDoc.txt
а также
$ echo $(ls)
myDoc.html SomeDirectory someDoc.txt
Выполняется первый, ls
который, как я понимаю, добавляет содержимое текущего рабочего каталога в stdout
файл (это то, что отображает терминал). Это верно?
Вторая получает значение ls
команды (что означает содержимое текущего рабочего каталога) и печатает его в stdout
файл. Это верно?
Почему две команды дают разные результаты?
ls
само по себе не дает вам несколько элементов в строке?echo *
?Ответы:
Когда вы запускаете эту команду:
терминал отображает вывод
ls
.Когда вы запускаете эту команду:
оболочка захватывает выходные данные
$(ls)
и выполняет разбиение по ним. По умолчаниюIFS
это означает, что все последовательности пробелов, включая символы новой строки, заменяются одним пробелом. Вот почему выводecho $(ls)
выводится в одной строке.Для расширенного обсуждения разделения слов, см . Часто задаваемые вопросы Грега .
Подавление разделения слов
Оболочка не выполняет разбиение слов на строки в кавычках. Таким образом, вы можете подавить разбиение слов и сохранить многострочный вывод с помощью:
ls
и многострочный выводВозможно, вы заметили, что
ls
иногда печатает более одного файла в строке:Это значение по умолчанию, когда вывод
ls
идет на терминал. Когда вывод не идет непосредственно к терминалу,ls
меняет его по умолчанию на один файл на строку:Это поведение задокументировано в
man ls
.Еще одна тонкость: подстановка команд и конечные строки
$(...)
является подстановкой команды, и оболочка удаляет завершающие символы новой строки из вывода подстановки команды . Обычно это не заметно, потому что по умолчаниюecho
добавляет одну новую строку в конец вывода. Таким образом, если вы потеряете один символ новой строки в конце,$(...)
и вы получите один изecho
, нет никаких изменений. Однако, если вывод вашей команды заканчивается 2 или более символами новой строки, в то время какecho
добавляется только один, в вашей выдаче будет отсутствовать один или несколько символов новой строки. В качестве примера, мы можем использоватьprintf
для генерации конечных символов новой строки. Обратите внимание, что обе следующие команды, несмотря на разное количество новых строк, выдают одинаковый вывод одной пустой строки:Это поведение задокументировано в
man bash
.Еще один сюрприз: расширение пути, дважды
Давайте создадим три файла:
Обратите внимание на разницу между
ls file?
иecho $(ls file?)
:В случае
echo $(ls file?)
, глобус файлаfile?
раскрывается дважды , в результате чего имена файловfile1
иfile2
дважды появляются в выводе. Это связано с тем, что, как указывает Джеффикинс, расширение имени пути выполняется сначала оболочкой передls
запуском, а затем снова передecho
запуском.Второе расширение пути может быть подавлено, если мы использовали двойные кавычки:
источник
isatty
вы можете проверить, является ли stdout tty, ls использует это, чтобы определить, использовать ли цвета или нет.$( )
фактически обеспечивает синтаксический барьер, поэтому вам не нужно интерполировать?$()
обеспечивает синтаксический барьер.echo
команда расширит подстановочный знак . Например, еслиls
возвращает файл? file1 file2 , тогдаecho $(ls)
вернет файл? файл1 файл2 файл1 файл2 .echo
не расширяет подстановочные знаки; оболочка выполняет перед передачей полученного расширения в качестве аргументовecho
.ls
знает, отправляет ли он вывод на терминал или нет.Выполнение
ls
в командной строке запишет в ваш псевдо-tty. Перенаправление выводаls
, как правило, не будет передаваться псевдо-tty иls
будет форматировать вывод иначе.источник