programas - ¿Qué método debo usar para escribir mensajes de error en ''stderr'' usando ''printf'' en un script de bash?
programacion shell linux ejemplos (4)
Eso me parece razonable. Sin embargo, no necesita el
1
; funcionará como está, pero está implícito:printf "{%s} This should go to stderr./n" "$(date)" >&2
Tienes un problema de orden de operaciones:
$ 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.
Quiero dirigir la salida de un printf
en un script de bash
a stderr
lugar de stdout
.
No estoy preguntando acerca de la redirección de stderr
o stdout
desde donde se encuentren actualmente enrutados. Solo quiero poder enviar la salida de un printf
a stderr
lugar de al valor predeterminado de stdout
.
Experimenté un poco y descubrí que agregar 1>&2
al printf
, como se muestra en el siguiente ejemplo, parece hacer lo que quiero. Sin embargo, no tengo experiencia usando bash. ¿Entonces mi pregunta principal es si hay una forma " mejor " de hacer esto en bash
?
Por " mejor " me refiero a si hay otra forma de hacer esto que sea más comúnmente utilizada, más convencional o más idiomática. ¿Cómo lo haría un programador de bash más experimentado?
#!/bin/bash
printf "{%s} This should go to stderr./n" "$(date)" 1>&2
printf "[(%s)] This should go to stdout./n" "$(date)"
También tengo una pregunta secundaria . Lo pregunto no tanto porque necesito saberlo, sino más bien porque tengo curiosidad y me gustaría entender mejor lo que está sucediendo.
Parece que lo anterior solo funcionará cuando se ejecuta dentro de un script de shell. No parece funcionar cuando lo intento desde una línea de comandos.
Aquí hay un ejemplo de lo que quiero decir.
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
Espero que el comando printf
anterior no tenga salida porque la salida debería ir a stderr
, que a su vez debería ir a un archivo. Pero esto no sucede. Eh
La pregunta parece indicar cierta confusión. No desea redireccionar stdout, solo desea que printf envíe su salida a stderr ... Pero para eso, debe usar la redirección.
El comando printf siempre envía la salida normal a su stdout. Eso es lo que hace printf. Para lograr lo que desea, debe tener la configuración de shell que stdout apunta temporalmente a donde desea que vaya la salida. Fíjate que digo temporalmente. Cuando escribes un comando como
$ printf "Hello World!" >&2
el shell modifica el controlador stdout durante la ejecución de la sentencia printf. Luego, el shell restaura el valor original de la salida estándar antes de continuar con el siguiente comando. De hecho, si desea redireccionar la salida estándar de forma permanente, use el comando especial
$ exec >&2
Después de que el shell haya ejecutado esto, el shell ya no recuerda el valor original del controlador stdout.
Los modismos típicos son:
echo foo >&2 # you don''t need to specify file descriptor 1
echo foo > /dev/stderr # more explicit, but wordier and less portable
Primero, sí, 1>&2
es lo correcto.
En segundo lugar, la razón por la que su ejemplo 1>&2 2>errors.txt
no funciona es debido a los detalles de lo que hace exactamente la redirección.
1>&2
significa "hacer que el identificador de archivo 1 apunte a dondequiera que el identificador de archivo 2 actualmente", es decir, las cosas que se hubieran escrito en stdout ahora van a stderr. 2>errors.txt
significa "abrir un errors.txt
de errors.txt
a errors.txt
y hacer que el errors.txt
de errors.txt
2 apunte a él", es decir, las cosas que se hubieran escrito en stderr ahora errors.txt
en errors.txt
. Pero el identificador de archivo 1 no se ve afectado en absoluto, por lo que las cosas escritas en stdout todavía van a stderr.
Lo correcto es 2>errors.txt 1>&2
, que hará que las escrituras tanto en stderr como en stdout vayan a errors.txt
, porque la primera operación será "abrir errors.txt
y hará que stderr apunte a él", y la segunda operación será "hacer que stdout apunte a donde stderr apunta ahora".