Let's say I have a script like the following:
useless.sh
echo "This Is Error" 1>&2
echo "This Is Output"
And I have another shell script:
alsoUseless.sh
./useless.sh | sed 's/Output/Useless/'
I want to capture "This Is Error", or any other stderr from useless.sh, into a variable. Let's call it ERROR.
Notice that I am using stdout for something. I want to continue using stdout, so redirecting stderr into stdout is not helpful, in this case.
So, basically, I want to do
./useless.sh 2> $ERROR | ...
but that obviously doesn't work.
I also know that I could do
./useless.sh 2> /tmp/Error
ERROR=`cat /tmp/Error`
but that's ugly and unnecessary.
Unfortunately, if no answers turn up here that's what I'm going to have to do.
I'm hoping there's another way.
Anyone have any better ideas?
There are a lot of duplicates for this question, many of which have a slightly simpler usage scenario where you don't want to capture stderr and stdout and the exit code all at the same time.
works for the common scenario where you expect either proper output in the case of success, or a diagnostic message on stderr in the case of failure.
Note that the shell's control statements already examine
$?
under the hood; so anything which looks likeis just a clumsy, unidiomatic way of saying
Redirected stderr to stdout, stdout to /dev/null, and then use the backticks or
$()
to capture the redirected stderr:alsoUseless.sh
This will allow you to pipe the output of your
useless.sh
script through a command such assed
and save thestderr
in a variable namederror
. The result of the pipe is sent tostdout
for display or to be piped into another command.It sets up a couple of extra file descriptors to manage the redirections needed in order to do this.
This is an interesting problem to which I hoped there was an elegant solution. Sadly, I end up with a solution similar to Mr. Leffler, but I'll add that you can call useless from inside a Bash function for improved readability:
All other kind of output redirection must be backed by a temporary file.
It would be neater to capture the error file thus:
The shell recognizes this and doesn't have to run '
cat
' to get the data.The bigger question is hard. I don't think there's an easy way to do it. You'd have to build the entire pipeline into the sub-shell, eventually sending its final standard output to a file, so that you can redirect the errors to standard output.
Note that the semi-colon is needed (in classic shells - Bourne, Korn - for sure; probably in Bash too). The '
{}
' does I/O redirection over the enclosed commands. As written, it would capture errors fromsed
too.(Formally untested code - use at own risk.)