Il comando funziona in modo diverso a seconda del destinatario


12

In che modo comandi simili lssanno qual è il suo stdout?

Sembra che lsfunzioni in modo diverso a seconda di quale sia lo stdout di destinazione. Ad esempio se lo faccio:

ls /home/matt/tmp 

il risultato è:

a.txt b.txt c.txt

Comunque se lo faccio

ls /home/matt/tmp | cat

il risultato è (cioè nuova riga per risultato):

a.txt
b.txt
c.txt

Il processo è passato un descrittore di file 1 per stdout giusto? Come determina come formattare il risultato? Il descrittore di file rivela informazioni?


Correlati unix.stackexchange.com/q/157285/4671 , unix.stackexchange.com/q/63108/4671 e probabilmente altri. Sembra essere un argomento popolare. Questo potrebbe essere un inganno di uno di questi.
Faheem Mitha,

Risposte:


22

Il lsprogramma usa isatty()per sapere se fd 1 è un tty o qualcos'altro (pipe, file, ecc ...). Da man 3 isatty:

int isatty(int fd);

DESCRIZIONE
La isatty()funzione verifica se si fdtratta di un descrittore di file aperto che fa riferimento a un terminale


Aggiornamento: riga 1538 in ls.cda coreutils (revisione git 43a987e1):

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

( many_per_linedovrebbe essere auto-descrittivo.)


8

Non una risposta esatta ma un'esemplificazione. In uno script Bash puoi ottenere un effetto simile con test/ [['s -t:

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

Usandolo in questo modo:

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

Dal ls(1) manuale OpenBSD :

Per impostazione predefinita, ls elenca una voce per riga nell'output standard; le eccezioni sono ai terminali o quando sono specificate le opzioni -C, -m o -x.

Poi più tardi:

-1 (La cifra numerica `` uno ''.) Forza l'uscita a essere una voce per riga. Questo è il valore predefinito quando l'output non è verso un terminale.

[...]

-C Forza l'uscita multi-colonna; questo è il valore predefinito quando l'output è verso un terminale.


1

Puoi eseguire lsin uno pseudo-terminale usando il script comando, reindirizzare l'output lsa un altro comando e ottenere lo stesso formato di output come se non ci fosse tale piping del flusso stdout, cioè come se stdout fosse un terminale (tty).

Per sottostante isatty()meccanismo già sottolineato da Stéphane Gimenez vedere 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.