Quelle méthode dois-je utiliser pour écrire des messages d'erreur à 'stderr' en utilisant 'printf' dans un script bash?

je veux diriger la sortie d'un printf dans un bash script à stderr au lieu de stdout.

je suis demander à propos de la redirection stderr ou stdout d'où ils sont actuellement acheminés. Je veux juste être en mesure d'envoyer la sortie d'un printfstderr au lieu de la valeur par défaut de stdout.

j'ai testé un peu et a trouvé que l'ajout de 1>&2printf, comme illustré dans l'exemple ci-dessous, semble ne ce que je veux. Cependant, j'ai aucun expérience de l'utilisation de bash. Donc, mon primaire question est de savoir si il y a un "mieux" moyen de le faire dans bash?

Parmieux" je veux dire, est-il une autre façon de faire ce qui est plus couramment utilisé, plus classiques, ou plus idiomatique? Comment un programmeur de bash plus expérimenté le ferait-il?

#!/bin/bash
printf "{%s}   This should go to stderr.n" "$(date)" 1>&2 
printf "[(%s)] This should go to stdout.n" "$(date)" 

j'ai aussi un secondaire question. Je suis Je ne le demande pas tant parce que je le demande!--24-->besoin pour savoir, mais plus encore parce que je suis juste curieux et que je voudrais avoir une meilleure compréhension de ce qui se passe.

il semble que ce qui précède ne fonctionne que lorsqu'il s'exécute à l'intérieur d'un script shell. Il ne semble pas fonctionner quand je l'ai essayer en ligne de commande.

Voici un exemple de ce que je veux dire.

irrational@VBx64:~$ printf "{%s} Sent to stderr.n" "$(date)" 1>&2 2> errors.txt
{Sat Jun  9 14:08:46 EDT 2012} Sent to stderr.
irrational@VBx64:~$ ls -l errors.txt
-rw-rw-r-- 1 irrational irrational 0 Jun  9 14:39 errors.txt

j'attendrais la printf commande ci-dessus pour n'avoir aucune sortie parce que la sortie devrait aller à stderr, qui à son tour devrait aller vers un fichier. Mais cela n'arrive pas. Hein?

24
demandé sur Løiten 2012-06-09 22:48:52

4 réponses

tout d'Abord, oui, 1>&2 est la bonne chose à faire.

Deuxièmement, la raison de votre 1>&2 2>errors.txt exemple ne fonctionne pas est parce que les détails de exactement ce que la redirection ne.

1>&2 signifie "make filehandle 1 point to wherever filehandle 2 does currently" - c'est-à-dire que les choses qui auraient été écrites à stdout vont maintenant à stderr. 2>errors.txt signifie "ouvrir une manchette à errors.txt et faire descripteur 2 point à lui" - c'est à dire des trucs qui ont été écrits sur la sortie stderr maintenant va dans errors.txt. Mais filehandle 1 n'est pas affecté du tout, donc les choses écrites à stdout vont toujours à stderr.

La bonne chose à faire est de 2>errors.txt 1>&2, ce qui fera passer les Écritures à la fois à stderr et à stdout à errors.txt, parce que la première opération sera "open errors.txt et faire stderr point", et le second de l'opération de "faire stdout le point où stderr pointe maintenant".

26
répondu hobbs 2014-10-07 20:20:20
  1. cela me semble raisonnable. Vous n'avez pas besoin de l' 1, cependant, il va fonctionner ainsi, mais il est implicite:

    printf "{%s}   This should go to stderr.\n" "$(date)" >&2 
    
  2. Vous avez un ordre d'opérations problème:

    $ printf "{%s} Sent to stderr.\n" "$(date)" 2> errors.txt 1>&2
    $ ls -l errors.txt 
    -rw-r--r--  1 carl  staff  47 Jun  9 11:51 errors.txt
    $ cat errors.txt 
    {Sat Jun  9 11:51:48 PDT 2012} Sent to stderr.
    
7
répondu Carl Norum 2012-06-09 18:52:45

La question semble indiquer une certaine confusion. Vous ne voulez pas rediriger stdout, vous voulez juste que printf envoie sa sortie à stderr... Mais pour cela, vous devez utiliser la redirection.

la commande printf envoie toujours la sortie normale à son stdout. C'est ce que fait printf. Afin d'atteindre ce que vous voulez, vous devez avoir le shell organiser que stdout pointe temporairement à l'endroit où vous voulez que la sortie aille. Remarquez que je dis temporairement. Lorsque vous tapez une commande comme

$ printf "Hello World!" >&2

le shell modifie la poignée stdout pour la durée de l'exécution de la déclaration printf. Puis le shell rétablit la valeur originale de stdout avant de continuer avec la commande suivante. En fait, si vous voulez rediriger stdout de façon permanente, vous utilisez la commande spéciale

$ exec >&2

après que le shell a exécuté ceci, le shell ne se souvient plus de la valeur originale du manche stdout.

3
répondu Enrique Perez-Terron 2016-04-25 01:13:36

Les expressions idiomatiques typiques sont:

echo foo >&2           # you don't need to specify file descriptor 1
echo foo > /dev/stderr # more explicit, but wordier and less portable
2
répondu Todd A. Jacobs 2012-06-09 21:18:25