Differences between revisions 1 and 12 (spanning 11 versions)
Revision 1 as of 2007-05-02 23:38:27
Size: 2975
Editor: redondos
Comment:
Revision 12 as of 2010-05-11 05:23:15
Size: 3280
Editor: p5B09615D
Comment: fixed links
Deletions are marked like this. Additions are marked like this.
Line 1: Line 1:
[[Anchor(faq47)]] <<Anchor(faq47)>>
Line 3: Line 3:
                                                                                 A pipe can only carry stdout of a program. To pipe 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:
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:
Line 10: Line 6:
# - 'myprog' is an example for a program that outputs both, stdout and
# stderr
# - after the pipe I will just use a 'cat', of course you can put there
# what you want
# Bourne
# Assume 'myprog' is a program that writes to both stdout and stderr.
Line 15: Line 9:
# version 1: redirect stderr towards the pipe while stdout survives (both come # version 1: redirect stderr to the pipe while stdout survives (both come
Line 17: Line 11:
myprog 2>&1 | cat                                                               
                                                                                
# version 2: redirect stderr towards the pipe without getting stdout (it's
myprog 2>&1 | grep ...

# version 2: redirect stderr to the pipe without getting stdout (it's
Line 21: Line 15:
myprog 2>&1 >/dev/null | cat
#Note that '>/dev/null' comes after '2>&1', otherwise the stderr will also be di
rected to /dev/null
                                                                                
# version 3: redirect stderr towards the pipe while the "original" stdout gets
myprog 2>&1 >/dev/null | grep ...

# version 3: redirect stderr to the pipe while the "original" stdout gets
Line 26: Line 19:
myprog 2>&1 >&- | cat myprog 2>&1 >&- | grep ...
Line 29: Line 22:
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.

This has an obvious application with eg. dialog, which draws (using ncurses) windows onto the screen to stdout, and returns output to stderr. This may be a little inconvenient, because it may lead to a necessary temporary file which we may like to evade. (Although this is not necessary -- see [#faq40 FAQ #40] for more examples of using dialog specifically!)

On [http://www.tldp.org/LDP/abs/html/io-redirection.html TLDP], I've found following trick:
Another simple example of redirection stdout and stderr:
Line 35: Line 24:
# Redirecting only stderr to a pipe.

exec 3>&1 # Save current "value" of stdout.
ls -l /dev/fd/ 2>&1 >&3 3>&- | grep bad 3>&- # Close fd 3 for 'grep' and 'ls'.
# ^^^^ ^^^^
exec 3>&- # Now close it for the remainder of the script.

# Thanks, S.C.
# Bourne
{ command | stdout_reader; } 2>&1 | stderr_reader
Line 45: Line 28:
The output of the ls command shows where each file descriptor points to. For further explanation of how redirections and pipes interact, see [[BashFAQ/055|FAQ #55]].
Line 47: Line 30:
The same can be done without exec: 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.
Line 49: Line 35:
{ ls -l /dev/fd/ 2>&1 1>&3 3>&- | grep bad 3>&-; } 3>&1 # 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
Line 52: Line 45:
To show it as a dialog one-liner: The same can be done without {{{exec}}}:
Line 54: Line 47:
# POSIX
$ myfunc () { echo "I'm stdout"; echo "I'm stderr" >&2; }
$ { myfunc 2>&1 1>&3- | cat > stderr.file 3>&-; } 3>&1
I'm stdout
$ cat stderr.file
I'm stderr
}}}

The fd 3 is closed (1>&3- and 3>&-) so that the commands do not inherit it.
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
Line 55: Line 67:
dialog --menu Title 0 0 0 FirstItem FirstDescription 2>&1 >&3 3>&- | sed 's/First/Only/' dialog --menu Title 0 0 0 FirstItem FirstDescription 2>&1 >&3 | sed 's/First/Only/'
Line 59: Line 71:
This will have the dialog window working properly, yet it will be the output of dialog (returned to stderr) being altered by the sed. Cheers. This will have the {{{dialog}}} window working properly, yet it will be the output of {{{dialog}}} (returned to stderr) being altered by the {{{sed}}}.
Line 61: Line 73:
A similar effect can be achieved with process substitution: A similar effect can be achieved with ProcessSubstitution:
Line 63: Line 75:
perl -e 'print "stdout\n"; warn "stderr\n"' 2> >(tr a-z A-Z) # Bash
perl -e 'print "stdout\n"; warn "stderr\n"' 2> >(tr '[:lower:]' '[:upper:]')
Line 65: Line 78:
This will pipe standard error through the tr command.
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).

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 ...

# version 3: redirect stderr to the pipe while the "original" stdout gets
# closed
myprog 2>&1 >&- | 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 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 FAQ #40 for examples of using dialog specifically!

In the examples above (as well as 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- | cat  > stderr.file 3>&-; } 3>&1
I'm stdout
$ cat stderr.file
I'm stderr

The fd 3 is closed (1>&3- and 3>&-) so that the commands do not inherit it. 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 redirection tutorial (with an example that redirects stdout to one pipe and stderr to another pipe).

BashFAQ/047 (last edited 2012-03-05 11:30:04 by pgas)