Когда вы запускаете эту команду:
ls
терминал отображает вывод ls
.
Когда вы запускаете эту команду:
echo $(ls)
оболочка захватывает выходные данные $(ls)
и выполняет разбиение по ним. По умолчанию IFS
это означает, что все последовательности пробелов, включая символы новой строки, заменяются одним пробелом. Вот почему вывод echo $(ls)
выводится в одной строке.
Для расширенного обсуждения разделения слов, см . Часто задаваемые вопросы Грега .
Подавление разделения слов
Оболочка не выполняет разбиение слов на строки в кавычках. Таким образом, вы можете подавить разбиение слов и сохранить многострочный вывод с помощью:
echo "$(ls)"
ls
и многострочный вывод
Возможно, вы заметили, что ls
иногда печатает более одного файла в строке:
$ ls
file1 file2 file3 file4 file5 file6
Это значение по умолчанию, когда вывод ls
идет на терминал. Когда вывод не идет непосредственно к терминалу, ls
меняет его по умолчанию на один файл на строку:
$ echo "$(ls)"
file1
file2
file3
file4
file5
file6
Это поведение задокументировано в man ls
.
Еще одна тонкость: подстановка команд и конечные строки
$(...)
является подстановкой команды, и оболочка удаляет завершающие символы новой строки из вывода подстановки команды . Обычно это не заметно, потому что по умолчанию echo
добавляет одну новую строку в конец вывода. Таким образом, если вы потеряете один символ новой строки в конце, $(...)
и вы получите один из echo
, нет никаких изменений. Однако, если вывод вашей команды заканчивается 2 или более символами новой строки, в то время как echo
добавляется только один, в вашей выдаче будет отсутствовать один или несколько символов новой строки. В качестве примера, мы можем использовать printf
для генерации конечных символов новой строки. Обратите внимание, что обе следующие команды, несмотря на разное количество новых строк, выдают одинаковый вывод одной пустой строки:
$ echo "$(printf "\n")"
$ echo "$(printf "\n\n\n\n\n")"
$
Это поведение задокументировано в man bash
.
Еще один сюрприз: расширение пути, дважды
Давайте создадим три файла:
$ touch 'file?' file1 file2
Обратите внимание на разницу между ls file?
и echo $(ls file?)
:
$ ls file?
file? file1 file2
$ echo $(ls file?)
file? file1 file2 file1 file2
В случае echo $(ls file?)
, глобус файла file?
раскрывается дважды , в результате чего имена файлов file1
и file2
дважды появляются в выводе. Это связано с тем, что, как указывает Джеффикинс, расширение имени пути выполняется сначала оболочкой перед ls
запуском, а затем снова перед echo
запуском.
Второе расширение пути может быть подавлено, если мы использовали двойные кавычки:
$ echo "$(ls file?)"
file?
file1
file2