La commande ls fonctionne différemment selon le destinataire


12

Comment les commandes comme lssavent-elles quelle est leur sortie standard?

Il semble lsfonctionner différemment en fonction de la cible standard. Par exemple, si je le fais:

ls /home/matt/tmp 

le résultat est:

a.txt b.txt c.txt

Mais si je le fais

ls /home/matt/tmp | cat

le résultat est (ie nouvelle ligne par résultat):

a.txt
b.txt
c.txt

Le processus est passé un descripteur de fichier 1 pour stdout à droite? Comment détermine-t-il comment formater le résultat? Le descripteur de fichier révèle-t-il des informations?


Connexes unix.stackexchange.com/q/157285/4671 , unix.stackexchange.com/q/63108/4671 et probablement d'autres. Cela semble être un sujet populaire. Cela pourrait être une dupe de l'un d'eux.
Faheem Mitha

Réponses:


22

Le lsprogramme utilise isatty()pour savoir si fd 1 est un tty ou autre chose (pipe, fichier, etc…). De man 3 isatty:

int isatty(int fd);

DESCRIPTION
La isatty()fonction teste si fdun descripteur de fichier ouvert fait référence à un terminal


Mise à jour: ligne 1538 ls.cdepuis coreutils (révision git 43a987e1):

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

( many_per_linedevrait être auto-descriptif.)


8

Pas une réponse exacte mais une exemplification. Dans un script Bash , vous pouvez obtenir un effet similaire avec test/ [[« s -t:

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

L'utiliser comme ceci:

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

Depuis le ls(1) manuel d' OpenBSD :

Par défaut, ls répertorie une entrée par ligne vers la sortie standard; les exceptions concernent les terminaux ou lorsque les options -C, -m ou -x sont spécifiées.

Puis, plus tard:

-1 (Le chiffre numérique `` un ''.) Force la sortie à une entrée par ligne. Il s'agit de la valeur par défaut lorsque la sortie n'est pas vers un terminal.

[...]

- Forcer la sortie multi-colonnes; c'est la valeur par défaut lorsque la sortie est vers un terminal.


1

Vous pouvez exécuter lsdans un pseudo-terminal à l'aide de la script commande, diriger la sortie de lsvers une autre commande et obtenir le même format de sortie que s'il n'y avait pas de telle tuyauterie du flux stdout, c'est-à-dire comme si stdout était un terminal (tty).

Pour le sous - jacent isatty()mécanisme déjà signalé par Stéphane Gimenez voir 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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.