Когда вы запускаете эту команду:
ls
терминал отображает вывод LS
.
Когда вы запускаете эту команду:
echo $(ls)
оболочка захватывает вывод $ (ls)
и выполняет разбиение слов на нем. При использовании по умолчанию IFS
это означает, что все последовательности пробелов, , включая символов новой строки, заменяются одним пробелом. Поэтому вывод echo $ (ls)
отображается в одной строке.
Для более подробного обсуждения разбиения слов см. FAQ Грега .
Оболочка не выполняет разбиение слов на строках в кавычках. Таким образом, вы можете подавить разделение слов и сохранить многострочный вывод с помощью:
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
, изменений не будет. Однако, если вывод вашей команды заканчивается двумя или более символами новой строки, а 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