Differences between revisions 1 and 2
Revision 1 as of 2007-05-02 23:38:27
Size: 2975
Editor: redondos
Comment:
Revision 2 as of 2007-05-07 18:34:43
Size: 3018
Editor: GreyCat
Comment: lots of clean-up
Deletions are marked like this. Additions are marked like this.
Line 6: Line 6:
you can close stdout or redirect it to /dev/null to only get stderr. Some you can close stdout or redirect it to {{{/dev/null}}} to only get stderr. Some
Line 10: Line 10:
# - '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
# Assume 'myprog' is a program that outputs both, stdout and stderr.
Line 17: Line 14:
myprog 2>&1 | cat
                                                                                
myprog 2>&1 | grep ...
Line 21: Line 18:
myprog 2>&1 >/dev/null | cat
#Note that '>/dev/null' comes after '2>&1', otherwise the stderr will also be directed to /dev/null
                                                                                
myprog 2>&1 >/dev/null | grep ...
Line 26: Line 22:
myprog 2>&1 >&- | cat myprog 2>&1 >&- | grep ...
Line 29: Line 25:
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. For further explanation of how redirections and pipes interact, see [#faq55 FAQ #55].
Line 31: Line 27:
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!) 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 [#faq40 FAQ #40] for examples of using dialog specifically!
Line 33: Line 29:
On [http://www.tldp.org/LDP/abs/html/io-redirection.html TLDP], I've found following trick: In the examples above (as well as [#faq40 FAQ #40]), we either discarded stderr 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 35: Line 32:
# Redirecting only stderr to a pipe. # Redirect stderr to a pipe, keeping stdout unaffected.
Line 37: Line 34:
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.
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.
Line 42: Line 38:
# Thanks, S.C. # Thanks to http://www.tldp.org/LDP/abs/html/io-redirection.html
Line 45: Line 41:
The output of the ls command shows where each file descriptor points to.

The same can be done without exec:
The same can be done without {{{exec}}}:
Line 52: Line 46:
To show it as a dialog one-liner: (The {{{3>&-}}} redirections and the choices of {{{ls -l /dev/fd/}}} and {{{grep bad}}} in the preceding example seem to have been put in place to exhibit specific behaviors on some sort of Linux platform; however, in my testing, I have been unable to reproduce whatever behavior it was. It was probably specific to a certain kernel version which is no longer available to me personally. -- GreyCat)

To show a {{{dialog}}} one-liner:
Line 55: Line 51:
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 55:
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 63: Line 59:
# Bash only.
Line 65: Line 62:
This will pipe standard error through the tr command.
This will pipe standard error through the {{{tr}}} command.

Anchor(faq47)

How can I redirect stderr to a pipe?

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:

# Assume 'myprog' is a program that outputs both, stdout and stderr.

# version 1: redirect stderr towards the pipe while stdout survives (both come
# mixed)
myprog 2>&1 | grep ...

# version 2: redirect stderr towards the pipe without getting stdout (it's
# redirected to /dev/null)
myprog 2>&1 >/dev/null | grep ...

# version 3: redirect stderr towards the pipe while the "original" stdout gets
# closed
myprog 2>&1 >&- | grep ...

For further explanation of how redirections and pipes interact, see [#faq55 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 [#faq40 FAQ #40] for examples of using dialog specifically!

In the examples above (as well as [#faq40 FAQ #40]), we either discarded stderr 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.

# 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:

{ ls -l /dev/fd/ 2>&1 1>&3 3>&- | grep bad 3>&-; } 3>&1

(The 3>&- redirections and the choices of ls -l /dev/fd/ and grep bad in the preceding example seem to have been put in place to exhibit specific behaviors on some sort of Linux platform; however, in my testing, I have been unable to reproduce whatever behavior it was. It was probably specific to a certain kernel version which is no longer available to me personally. -- GreyCat)

To show a dialog one-liner:

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 process substitution:

# Bash only.
perl -e 'print "stdout\n"; warn "stderr\n"' 2> >(tr a-z A-Z)

This will pipe standard error through the tr command.

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