Search code examples
bashstdoutstdinstderr

forward stdin to stdout


I'm looking for a way to "forward" stdin to stdout in a pipe, while in that step something is written to stderr. The example should clarify this:

echo "before.." | >&2 echo "some logging..."; [[forward stdin>stdout]] | cat

This should put "before.." to stdout, meanwhile "some logging..." to stderr.

How to do that? Or is there maybe another quite different approach to this?


Solution

  • Here's a solution based on your comments:

    cat ~/.bashrc | tee >( cat -n >&2 ) | sort
    

    cat ~/.bashrc represents the start of your pipeline, producing some data.

    tee duplicates its input, writing to both stdout and any files listed as arguments.

    >( ... ) is a bash construct that runs ... as a pipe subcommand but replaces itself by a filename (something that tee can open and write to).

    cat -n represents modifying the input (adding line numbers).

    >&2 redirects stdout to stderr.

    sort represents the end of your pipeline (normal processing of the unchanged input).


    Putting it all together, bash will

    • run cat ~/.bashrc, putting the contents of ~/.bashrc on stdout
    • ... which is piped to the stdin of tee
    • run cat -n with stdout redirected to stderr and stdin redirected to a new pipe
    • run tee /dev/fd/63 (where /dev/fd/63 represents the other end of the cat -n pipe)
    • this is where it all comes together: tee reads its input and writes it to both its stdout and to the other pipe that goes to cat -n (and from there to stderr)
    • finally tee's stdout goes into sort