mostrar STDOUT antes de STDERR?

9

Soy nuevo en bash y no puedo por mi vida descubrir cómo ejecutar un determinado comando, supongamos ./fffe imprimo stdouts regulares antes de stderr (estoy confundido sobre el significado)

por ejemplo

$ printf "I am a\ndrill\n" > fff; 
$ cat fff nofile fff nofile fff

I am a
drill
cat: nofile: No such file or directory
I am a
drill
cat: nofile: No such file or directory
I am a
drill

necesita imprimir como:

I am a
drill
I am a
drill
I am a
drill
cat: nofile: No such file or directory
cat: nofile: No such file or directory

Entiendo que necesito redirigir mi salida primero a un archivo y luego agregar el error al mismo archivo, sin embargo, esta es la salida que obtengo

$ cat ./foo nofile ./foo nofile ./foo <<< $(touch fin) > see 2>> see 

I am a
drill
I am a
drill
I am a
drill
ectory
cat: nofile: No such file or directory
Maullar
fuente
2
¿ catRealmente reemplazó "a" por "algunos"?
Dmitry Grigoryev
oh dang, podría haber estropeado la cuerda. Lo editaré de inmediato @DmitryGrigoryev
MeOw

Respuestas:

18

Deberá mantener la salida stderr en algún lugar de todos modos para poder mostrarla al final.

Me viene a la mente un archivo :

fff 2> file; cat file >&2

O memoria (aquí usando spongedesde moreutils):

{ fff 2>&1 >&3 3>&- | sponge >&2 3>&-; } 3>&1
  • {...} 3>&1: dentro {...}del descriptor de archivo (fd) 3 puntos al mismo recurso que el stdout original (para que podamos usarlo para restaurar stdout fff).
  • fff <redirs> | sponge <redirs>, fffy spongecomenzó simultáneamente (con <redirs>aplicado independientemente) con la salida estándar que fffva a una tubería, y spongela entrada estándar es el otro extremo de la tubería.
  • 2>&1: fd 2 de fff(stderr) apunta a lo mismo que en 1: la tubería en este punto, por lo que fffel error pasa spongepor esa tubería.
  • >&3: ahora stdout apunta al stdout original (redirige de nuevo a lo que era)
  • 3>&-: cerramos fd 2 que fffno necesita
  • spongeacumula su entrada y solo la muestra (en su stdout que se ha redirigido >&2al mismo recurso que stderr) después de detectar eof en su stdin (se supone que es cuando ffftermina y ya ha escrito toda su salida en su stdout).

Si spongeno está instalado, puede reemplazarlo por perl -0777 -pe ''. Con -pe '', perllee un registro a la vez desde su entrada y lo escribe en stdout. -0777es el modo slurp donde el registro (solo uno en ese caso) es la entrada completa.

Stéphane Chazelas
fuente
Por favor, divídalo si tiene tiempo!
George Udosen
¿Podemos usar en teelugar de sponge...?
George Vasiliou
@GeorgeUdosen ver editar.
Stéphane Chazelas
1
@GeorgeVasiliou, teeno contiene datos, los escribe tan pronto como los lee.
Stéphane Chazelas
2
@MeOw: Eso está bien, pero, como muestra la tercera línea de la respuesta de Stéphane, no es necesario guardar el stdout; solo hazlo cat foo nofile foo nofile foo 2> ferr.txt; cat ferr.txt. (Y probablemente no quiera usarlo >>). Además, Stéphane hace el excelente punto que probablemente debería hacer cat ferr.txt >&2para escribir la información de stderr en el stderr.
G-Man dice 'Reincorporar a Monica' el