How to store standard error in a variable

psycotica0 picture psycotica0 · Jun 7, 2009 · Viewed 204.3k times · Source

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?

Answer

Jonathan Leffler picture Jonathan Leffler · Jun 7, 2009

It would be neater to capture the error file thus:

ERROR=$(</tmp/Error)

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.

ERROR=$( { ./useless.sh | sed s/Output/Useless/ > outfile; } 2>&1 )

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 from sed too.

WARNING: Formally untested code - use at own risk.