Команда ls работает по-разному в зависимости от получателя

12

Как такие команды, как lsузнать, что его стандартный вывод?

Кажется ls, работает по-разному в зависимости от того, что является целевым stdout. Например, если я делаю:

ls /home/matt/tmp 

результат:

a.txt b.txt c.txt

Однако если я сделаю

ls /home/matt/tmp | cat

результат (то есть новая строка на результат):

a.txt
b.txt
c.txt

Процесс передается файловый дескриптор 1 для stdout правильно? Как это определяет, как отформатировать результат? Дескриптор файла раскрывает информацию?

Мэтт Фрёман
источник
Связанные unix.stackexchange.com/q/157285/4671 , unix.stackexchange.com/q/63108/4671 и, возможно, другие. Кажется, это популярная тема. Это может быть обманом одного из них.
Фахим Митха

Ответы:

22

В lsпрограмме использует isatty()знать FD 1 , является ли TTY или что - то другое (трубы, файл, и т.д ...). От man 3 isatty:

int isatty(int fd);

ОПИСАНИЕ
В isatty()функции проверяет , является ли fdэто дескриптор открытого файла со ссылкой на терминал


Обновление: строка 1538 ls.cиз coreutils (git revision 43a987e1):

  if (isatty (STDOUT_FILENO))
    {
      format = many_per_line;
      /* See description of qmark_funny_chars, above.  */
      qmark_funny_chars = true;
    }

( many_per_lineдолжен быть информативным.)

Стефан Хименес
источник
8

Не точный ответ, а пример. В сценарии Bash вы можете достичь подобного эффекта с test/ [[«s -t:

-t FD True if FD is opened on a terminal.

Используя это так:

bash-4.2$ where() { [[ -t 1 ]] && echo 'my output goes to TTY' || echo 'my output is redirected'; }

bash-4.2$ where
my output goes to TTY

bash-4.2$ where | cat
my output is redirected

bash-4.2$ where > test.file
bash-4.2$ cat test.file
my output is redirected
manatwork
источник
6

Из OpenBSD ls(1) руководства :

По умолчанию ls перечисляет одну запись на строку для стандартного вывода; Исключения составляют терминалы или когда указаны параметры -C, -m или -x.

Тогда позже:

-1 (Цифровая цифра `` one ''.) Принудительно выводить по одной записи в строке. Это значение по умолчанию, когда вывод не на терминал.

[...]

-C Force многостолбцовых вывода; это значение по умолчанию, когда вывод на терминал.

Кусалананда
источник
1

Вы можете выполнить lsв псевдотерминале, используя script команду, перенаправить вывод lsв другую команду и получить тот же формат вывода, как если бы не было такого трубопровода потока stdout, т.е. как если бы stdout был терминалом (tty).

Для базового isatty()механизма уже указывалось Стефаном Хименес см ls.c .

ls -G /
ls -G / | cat
script -q /dev/null ls -G / | sed $'s/\r$//g' | cat

# tty | cat
# script -q /dev/null tty | cat
рон
источник