Polecenie ls działa inaczej w zależności od odbiorcy

12

Skąd takie polecenia lswiedzą, co to jest standardowe wyjście?

Wygląda na lsto, że działa inaczej w zależności od tego, co jest docelowe. Na przykład, jeśli zrobię:

ls /home/matt/tmp 

wynik to:

a.txt b.txt c.txt

Jeśli jednak to zrobię

ls /home/matt/tmp | cat

wynikiem jest (tj. nowa linia na wynik):

a.txt
b.txt
c.txt

Proces jest przekazywany deskryptorowi pliku 1 dla standardowego wejścia, prawda? Jak określa sposób sformatowania wyniku? Czy deskryptor pliku ujawnia informacje?

Mâtt Frëëman
źródło
Powiązane unix.stackexchange.com/q/157285/4671 , unix.stackexchange.com/q/63108/4671 i prawdopodobnie inne. To wydaje się być popularnym tematem. To może być duplikat jednego z nich.
Faheem Mitha

Odpowiedzi:

22

Do lszastosowania programu isatty()wiedzieć, czy fd 1 jest tty lub coś innego (rura, plików, itp ...). Od man 3 isatty:

int isatty(int fd);

OPIS
Te isatty()testy czynnościowe, czy fdjest otwarty plik opisu odnoszące się do terminala


Aktualizacja: Linia 1538 ls.cz Coreutils (git wersja 43a987e1):

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

( many_per_linepowinien być opisowy).

Stéphane Gimenez
źródło
8

Nie jest to dokładna odpowiedź, ale przykład. W skrypcie Bash możesz osiągnąć podobny efekt za pomocą test/ [['s -t:

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

Używając tego w ten sposób:

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
człowiek w pracy
źródło
6

Z ls(1) podręcznika OpenBSD :

Domyślnie ls wyświetla jeden wpis w wierszu na standardowe wyjście; wyjątki dotyczą terminali lub gdy podano opcje -C, -m lub -x.

Następnie:

-1 (cyfra `` jeden ''.) Wymusza na wyjściu jeden wpis na linię. Jest to ustawienie domyślne, gdy wyjście nie jest wysyłane do terminala.

[...]

-C Wymuś wyjście z wielu kolumn; jest to ustawienie domyślne, gdy wyjście jest wysyłane do terminala.

Kusalananda
źródło
1

Możesz wykonać lsw pseudo-terminalu za pomocą script polecenia, przesłać dane wyjściowe lsdo innego polecenia i uzyskać taki sam format wyjściowy, jak gdyby nie było takiego potoku strumienia standardowego, tzn. Jakby standardowe było terminalem (tty).

Dla bazowego isatty()mechanizmu wskazał już Stéphane Gimenez zobaczyć 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
Ron
źródło