Трубопровод ls такой же, как ls -1?

19

lsвозвращает вывод в нескольких столбцах, тогда как ls|catвозвращает идентичный байту вывод ls -1для каталогов, которые я пробовал. Тем не менее я вижу, что ls -1в ответах, как ls -1|wc -l. Есть ли причина отдавать предпочтение ls -1? Почему ...|catменяется выход ls?

rubystallion
источник
1
имена файлов могут содержать символы новой строки, так что вы можете посчитать их несколько раз ... вместо этого вы можете сделать следующее: n=0; for i in .* *; do ((n++)) ; done ; echo $n( опустите . *, если вы не хотите считать их). или: ls -1d ./.* ./* | grep '^\./' | wc -l (поскольку имена файлов не могут содержать '/')
Оливье Дюлак
3
lsвывод на терминал обычно включает цветовые коды по умолчанию. Для вывода на нетерминал цвет обычно отключен по умолчанию. В GNU это --color={always,auto,never}IIRC. Если цвет включен в один, а не в другой, то выходные данные могут отображаться на экране одинаковыми, но они не являются байтовыми (цветовые коды являются частью выходных данных ls).
CVn
@ MichaelKjörling Я думаю, ты должен написать это как ответ.
200_success
@ MichaelKjörling Это что-то интересное, что я не учел. Существует ли общий способ всегда передавать данные так, как будто они выводятся на терминал без необходимости запоминать параметры терминала для вывода цвета, столбцов и т. Д.?
rubystallion
@rubystallion Это звучит как хороший отдельный вопрос.
CVn

Ответы:

26

lsпроверяет, идет ли вывод в терминал. Если вывод не идет на терминал, то -1по умолчанию. (Это может быть отменено одним из -C, -mили -xопций.)

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

POSIX Технические характеристики

POSIX требует -1по умолчанию, когда вывод не идет на терминал:

Спецификация POSIX :

Формат по умолчанию должен содержать одну запись в строке для стандартного вывода; исключения относятся к терминалам или когда указана одна из опций -C, -m или -x. Если вывод на терминал, формат определяется реализацией.

Эти три параметра, которые переопределяют формат по умолчанию с одним столбцом:

-C
Записать вывод многотекстового столбца с записями, отсортированными по столбцам в соответствии с порядком сортировки. Количество текстовых столбцов и символы разделителя столбцов не определены, но их следует адаптировать к характеру устройства вывода. Эта опция отключает вывод в длинном формате.

-m
формат вывода потока; перечислить имена путей по странице, разделенные символом <запятая>, за которым следует символ <пробел>. Используйте символ <newline> как терминатор списка и после последовательности разделителей, когда в строке нет места для следующей записи списка. Эта опция отключает вывод в длинном формате.

-x
То же, что и -C, за исключением того, что вывод многотекстовых столбцов производится с записями, отсортированными по столбцам, а не по столбцам. Эта опция отключает вывод в длинном формате.

Документация GNU

Из руководства GNU ls :

'-1'
'--format = single-column'
Вывести один файл на строку. Это значение по умолчанию для ls, когда стандартный вывод не является терминалом . Смотрите также параметры -b и -q для подавления прямого вывода символов новой строки в имени файла. [Акцент добавлен]

Примеры

Давайте создадим три файла:

$ touch file{1..3}

Когда вывод поступает на терминал, GNU lsвыбирает использовать многостолбцовый формат:

$ ls
file1  file2  file3

Когда вывод идет в конвейер, спецификация POSIX требует, чтобы по умолчанию был один столбец:

$ ls | cat
file1
file2
file3

Три исключения, которые переопределяют поведение одного столбца по умолчанию, относятся -mк разделенным запятыми, -Cдля отсортированных -xпо столбцам и для сортированных по столбцам:

$ ls -m | cat
file1, file2, file3
$ ls -C | cat
file1  file2  file3
$ ls -x | cat
file1  file2  file3
John1024
источник
«POSIX требует -1 в качестве значения по умолчанию, когда вывод поступает на терминал:« ... но в кавычке указывается, что это требуется -1в качестве значения по умолчанию, за исключением случаев, когда вывод поступает на терминал (или другие условия)
Muru
@muru Спасибо, что поймали это! Ответ обновлен.
John1024
Ну, у каждого облака есть серебряная подкладка. Поскольку ваш ответ был принят до того, как мой был опубликован, я получил прикольную шляпу для пиццы!
G-Man говорит «Восстановить Монику»
@ G-Man Очень хорошо. И это красивая шляпа!
John1024
9
  • Почему использование стандартного вывода изменяет поведение ls? Потому что так было задумано. Спецификация POSIX говорит:

    Формат по умолчанию должен содержать одну запись в строке для стандартного вывода; исключения являются терминалами или когда один из -C, -mили -xопции указывается. Если вывод на терминал, формат определяется реализацией.

    что на самом деле неоднозначно по отношению к поведению по умолчанию (если оно не указано опцией вроде -lили -1) с выводом на терминал, а в документации GNU Coreutils говорится

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

    Таким образом, вы можете видеть, что вывод в файл будет действовать так же, как вывод в канал; то есть одна запись в строке, как если бы -1она была указана.

  • Почему это было разработано таким образом? Это может быть невозможно узнать наверняка (если кто-то не может найти некоторые заметки о дизайне), но я думаю:
    • Когда lsпишет в терминал, он ожидает, что человек смотрит на результат. Люди предпочитают получать информацию в минимально необходимом количестве строк, поэтому материал не прокручивается на экране.
    • Когда lsпишет в канал, он ожидает, что другая программа читает вывод. Для программы намного проще читать данные, которые имеют одно значение на строку, чем пытаться анализировать столбцы (поскольку имена файлов могут содержать пробелы).
  • Есть ли причина предпочитать, ls -1 когда вы пишете в файл или канал? Нет .
G-Man говорит: «Восстанови Монику»
источник
-4

При использовании ls, ls не может определить, сколько столбцов на самом деле имеет консоль (независимо от команды правой стороны). Поэтому я просто делаю это по своему выбору, или, другими словами, это поведение нестабильно и может измениться в будущих версиях.

Напротив, ls -1был создан с целью подсчета или сценариев в целом, поэтому его поведение является стабильным.

xanoetux
источник
9
Как и в других ответах, POSIX требует такого поведения, поэтому называть его нестабильным неправильно.
Хенрик - прекрати причинять боль Монике