I'm trying to create a general-purpose function or script that I can pipe data into, and prepend the output showing which fd the data "arrived" on (stdout or stderr). My Bash skills are intermediate at best, and I find myself in over my head trying to wrap my head around statements like { foo 2>&1 >&3 3>&- | bar 3>&-; } 3>&1
.
Can anyone suggest if this is possible, and a way to do it?
Essentially I want to do something like this:
$ { echo "foo" ; echo "bar" 1>&2 ; } | my_output_processor.sh
stdout: foo
stderr: bar
I've read Piping STDERR vs. STDOUT but that didn't answer it for me. I think the answer at https://unix.stackexchange.com/a/440439/307184 might contain a clue, but it seems that would work within the running script only, not with piped in data.
My Bash version is 5.0 on macOS.
edit: @Glenn's answer below is working! I made a couple of small helper functions to save a bit of typing and prevent errors, and tested like this:
$ out(){ sed "s/^/out: /" ;} ; err(){ sed "s/^/err: /" 1>&2 ;}
$ { echo "good" ; echo "bad" >&2; } 2> >(err) 1> >(out)
err: bad
out: good
Followup question about the ordering of the redirection: why does 2> >(err) 1> >(out)
work great, while 1> >(out) 2> >(err)
does not? (update: answered by @RudiC below - helper functions updated so they work in any order now)