Вывод ls имеет переводы строки, но отображается в одной строке. Зачем?

41

Я думаю, что я могу упускать из виду относительно фундаментальный момент в отношении оболочки. Вывод команды ls по умолчанию отделяет вывод с символами новой строки, но оболочка отображает вывод в одной строке.

Кто-нибудь может мне это объяснить? Я всегда предполагал, что выходные данные были просто разделены пробелами, но теперь, когда я вижу выходные данные, разделенные новыми строками, я ожидал, что выходные данные будут отображаться в отдельных строках.

Пример:

cpoweradm@debian:~/lpi103-4$ ls text*
text1  text2  text3

od показывает, что вывод разделен символами новой строки:

cpoweradm@debian:~/lpi103-4$ ls text* | od -c
0000000   t   e   x   t   1  \n   t   e   x   t   2  \n   t   e   x   t
0000020   3  \n
0000022

Если присутствуют новые строки, то почему вывод не отображается как:

text1 
text2
text3
zod90
источник

Ответы:

44

Когда вы транслируете вывод, lsдействует иначе.

Этот факт скрыт в информационной документации :

Если стандартным выводом является терминал, вывод выводится в столбцах (отсортированных по вертикали), а управляющие символы выводятся в виде вопросительных знаков; в противном случае вывод выводится по одному на строку, а управляющие символы выводятся как есть.

Чтобы доказать это, попробуйте запустить

ls

а потом

ls | less

Это означает, что если вы хотите, чтобы вывод гарантированно составлял один файл на строку, независимо от того, передается ли он по конвейеру или перенаправляется, вы должны запустить

ls -1

( -1это номер один)

Или вы можете заставить ls | lessвыводить в столбцах, запустив

ls -C

( -Cэто заглавная буква C)

Mikel
источник
6
@theconnorpower: это довольно специфично для ls. Это полезно, но явно противоречиво и удивительно. Но обратите внимание, что некоторые команды, которые производят цветной вывод, также удаляют цвета при передаче по конвейеру.
Микель
5
@theconnorpower: Общая информация: изобретатели Unix продолжили писать Plan9. В Plan9 lsвсегда печатает по одному на строку и lcвсегда печатает в столбцах.
Микель
2
@theconnorpower: Существуют также программы, которые считывают размер терминала и соответствующим образом корректируют его вывод, например, в Debian dpkg -lбудет использоваться вся ширина экрана, но если он печатает в канал, он предполагает, что терминал имеет ширину 80 столбцов. и сокращает вывод, чтобы он соответствовал при необходимости.
Микель
1
@Mikel Интересно услышать различия ls / lc в Plan9. Спасибо за подробный ответ.
zod90
1
Как программа может определить, перенаправлен ли ее вывод в файл или в оболочку?
user2820379
4

Ваше открытие выдвигает на первый план основную причину, по которой анализ результатов lsвсегда плохая идея. См. Вики Грега для полного объяснения .

Подумайте о своей проблеме в обратном порядке. Вы заметили, что ls иногда делает, а иногда не печатает переводы строк между выходными данными. Для использования в сценариях или когда принудительно установлен -1флагом, он делает. Одна новая строка в конце каждого файла. Что нет гарантии, что каждая новая строка представляет новое имя файла . На самом деле, если имя файла содержит новую строку, вывод ls будет абсолютно не разбираться. Рассмотрим эти имена файлов:

file1
file2\nfile3
file4

Когда вы ls -1каталог с этим в нем, вы получите что-то похожее на это:

file1
file2
file3
file4

Разве вы не предполагаете, что там было четыре файла? Как и любые сценарии, которые анализируют вывод ls. На самом деле есть три файла, один из которых с непростым именем, но вы не сможете понять это по выводу ls. *

* Если вы не использовали -lфлаг и не заметили, что вывод был прерван, но ваши сценарии все еще задыхались.

Калеб
источник
3
Если вам действительно нужно проанализировать вывод ls, -bопция может помочь. Превращает новую строку в \nи т. Д.
Микель