Команда ls працює по-різному, залежно від одержувача


12

Як команди, як-от, lsзнають, що таке її stdout?

Здається ls, працює по-різному, залежно від того, яка цільова верстка. Наприклад, якщо я це роблю:

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 та, ймовірно, інші. Здається, це популярна тема. Це, можливо, є одним із них.
Faheem Mitha

Відповіді:


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

6

З ls(1) посібника з OpenBSD :

За замовчуванням ls перераховує один запис на рядок до стандартного виводу; винятки становлять термінали або коли вказані параметри -C, -m або -x.

Потім, пізніше:

-1 (Цифрова цифра `` один ''.) Примушує виводити один запис на рядок. Це за замовчуванням, коли вихід не в термінал.

[...]

-C Форма виходу з декількох стовпців; це значення за замовчуванням, коли вихід на термінал.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.