<> == How can I redirect stderr to a pipe? == A pipe can only carry standard output (stdout) of a program. To pipe standard error (stderr) through it, you need to redirect stderr to the same destination as stdout. Optionally you can close stdout or redirect it to {{{/dev/null}}} to only get stderr. Some sample code: {{{ # Bourne # Assume 'myprog' is a program that writes to both stdout and stderr. # version 1: redirect stderr to the pipe while stdout survives (both come # mixed) myprog 2>&1 | grep ... # version 2: redirect stderr to the pipe without getting stdout (it's # redirected to /dev/null) myprog 2>&1 >/dev/null | grep ... # same idea, this time storing stdout in a file myprog 2>&1 >file | grep ... }}} Another simple example of redirection stdout and stderr: {{{ # Bourne { command | stdout_reader; } 2>&1 | stderr_reader }}} For further explanation of how redirections and pipes interact, see [[BashFAQ/055|FAQ #55]]. This has an obvious application with programs like {{{dialog}}}, which draws (using ncurses) windows onto the screen (stdout), and returns results on stderr. One way to deal with this would be to redirect stderr to a temporary file. But this is not necessary -- see [[BashFAQ/040|FAQ #40]] for examples of using dialog specifically! In the examples above (as well as [[BashFAQ/040|FAQ #40]]), we either discarded stdout altogether, or sent it to a known device ({{{/dev/tty}}} for the user's terminal). One may also pipe stderr only but keep stdout intact (without ''a priori'' knowledge of where the script's output is going). This is a bit trickier. {{{ # Bourne # Redirect stderr to a pipe, keeping stdout unaffected. exec 3>&1 # Save current "value" of stdout. myprog 2>&1 >&3 | grep ... # Send stdout to FD 3. exec 3>&- # Now close it for the remainder of the script. # Thanks to http://www.tldp.org/LDP/abs/html/io-redirection.html }}} The same can be done without {{{exec}}}: {{{ # POSIX $ myfunc () { echo "I'm stdout"; echo "I'm stderr" >&2; } $ { myfunc 2>&1 1>&3 3>&- | cat > stderr.file 3>&-; } 3>&1 I'm stdout $ cat stderr.file I'm stderr }}} The fd 3 is closed (3>&-) so that the commands do not inherit it. Note bash allows to duplicate and close in one redirection: 1>&3- You can check the difference on linux trying the following: {{{ # Bash { bash <<< 'lsof -a -p $$ -d1,2,3' ;} 3>&1 { bash <<< 'lsof -a -p $$ -d1,2,3' 3>&- ;} 3>&1 }}} To show a {{{dialog}}} one-liner: {{{ # Bourne exec 3>&1 dialog --menu Title 0 0 0 FirstItem FirstDescription 2>&1 >&3 | sed 's/First/Only/' exec 3>&- }}} This will have the {{{dialog}}} window working properly, yet it will be the output of {{{dialog}}} (returned to stderr) being altered by the {{{sed}}}. A similar effect can be achieved with ProcessSubstitution: {{{ # Bash perl -e 'print "stdout\n"; warn "stderr\n"' 2> >(tr '[:lower:]' '[:upper:]') }}} This will pipe standard error through the {{{tr}}} command. See this [[http://wiki.bash-hackers.org/howto/redirection_tutorial|redirection tutorial]] (with an example that redirects stdout to one pipe and stderr to another pipe). ---- CategoryShell