Der Befehl funktioniert je nach Empfänger unterschiedlich

11

Woher lswissen Befehle wie , was ihre Standardausgabe ist?

Es scheint lsunterschiedlich zu funktionieren, je nachdem, was das Ziel-Standard ist. Zum Beispiel, wenn ich:

ls /home/matt/tmp 

Das Ergebnis ist:

a.txt b.txt c.txt

Wenn ich es aber tue

ls /home/matt/tmp | cat

Das Ergebnis ist (dh neue Zeile pro Ergebnis):

a.txt
b.txt
c.txt

Dem Prozess wird ein Dateideskriptor 1 für stdout übergeben, oder? Wie wird festgelegt, wie das Ergebnis formatiert wird? Zeigt der Dateideskriptor Informationen an?

Mâtt Frëëman
quelle
Verwandte unix.stackexchange.com/q/157285/4671 , unix.stackexchange.com/q/63108/4671 und wahrscheinlich andere. Es scheint ein beliebtes Thema zu sein. Dies könnte ein Betrug von einem von diesen sein.
Faheem Mitha

Antworten:

21

Das lsProgramm verwendet, um isatty()zu wissen, ob fd 1 ein tty oder etwas anderes ist (Pipe, Datei usw.). Von man 3 isatty:

int isatty(int fd);

BESCHREIBUNG
Die isatty()Funktion prüft, ob fdes sich um einen offenen Dateideskriptor handelt, der sich auf ein Terminal bezieht


Aktualisierung: Zeile 1538 in ls.cvon 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_linesollte selbstbeschreibend sein.)

Stéphane Gimenez
quelle
8

Keine genaue Antwort, sondern ein Beispiel. In einem Bash-Skript können Sie mit test/ [['s einen ähnlichen Effekt erzielen -t:

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

Verwenden Sie es so:

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
Mann bei der Arbeit
quelle
6

Aus dem OpenBSD- ls(1) Handbuch :

Standardmäßig listet ls einen Eintrag pro Zeile für die Standardausgabe auf. Ausnahmen sind Terminals oder wenn die Optionen -C, -m oder -x angegeben sind.

Dann später:

-1 (Die numerische Ziffer "Eins".) Erzwingen Sie, dass die Ausgabe ein Eintrag pro Zeile ist. Dies ist die Standardeinstellung, wenn die Ausgabe nicht an ein Terminal erfolgt.

[...]

-C Mehrspaltige Ausgabe erzwingen; Dies ist die Standardeinstellung, wenn die Ausgabe an ein Terminal erfolgt.

Kusalananda
quelle
1

Sie können lsin einem Pseudo-Terminal mit dem script Befehl ausführen , die Ausgabe an lseinen anderen Befehl weiterleiten und das gleiche Ausgabeformat erhalten, als ob es keine solche Weiterleitung des stdout-Streams gäbe, dh als ob stdout ein Terminal (tty) wäre.

Für den zugrunde liegenden isatty()Mechanismus bereits von Stéphane Gimenez sehen hingewiesen 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
quelle