10

For this question I will use grep, because its usage text prints to stderr:

$ grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

You can capture stdout easily with process substitution:

$ read b < <(echo hello world)

However stderr slips past the process substitution and prints to the console:

$ read b < <(grep)
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.

I would like to capture stderr using process substitution. I am using this now:

$ grep 2> log.txt

$ read b < log.txt

but I am hoping to avoid the temp file.

halfer
  • 19,824
  • 17
  • 99
  • 186
Zombo
  • 1
  • 62
  • 391
  • 407

3 Answers3

15

Redirect the stderr of your command to stdout:

$ read "b" < <(grep 2>&1)
$ echo "$b"
Usage: grep [OPTION]... PATTERN [FILE]...

Though the conventional way to save the output of a command to a variable in Bash is by using $():

$ b=$(grep 2>&1)
$ echo "$b"
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
Christopher Neylan
  • 8,018
  • 3
  • 38
  • 51
2
$ grep 2> >(sed 's/e/E/g';)

You can capture grep's stdout and pipe it to sed but, I don't know why (nor how to avoid it) it needs an extra INTRO to return control and display the prompt.

Edit: You can fix that mismatch like this:

$ grep 2> >(sed 's/e/E/g';); sync
Robert Vila
  • 221
  • 3
  • 2
  • 2
    You are almost right. You have an unnecessary `;` in your process substitution. That's why you need `; sync` to fix this hang up. Just try: `grep 2> >(sed 's/e/E/g')`, and you will have straightaway an output. – John Goofy Jul 11 '17 at 18:02
1

A more general solution for a whole subshell is to use exec to redirect its standard error.

If, instead of the OP's example based on grep being a single command, you had a sequence of commands in the subshell then you can redirect the standard error of the whole subshell like this:

b=$(cat <(
    exec 2>&1
    echo "standard output"
    echo "standard error" 1>&2
   ))    

echo $b

which puts the output of standard output and standard error into the variable $b:

standard output standard error

The echo statements are just examples to output something to each of standard output and standard error.

starfry
  • 9,273
  • 7
  • 66
  • 96