Shell Scripting: Setting a Variable Equal to stderr

Recently I had to have a variable set equal to stderr output in a Bash script for the first time. After looking around a little, the way that one can accomplish this is completely reasonable and makes sense, it just wasn’t what immediately came to mind.

These solutions will include stdout and stderr in the same variable. I have yet to find a way to completely separate the output.

Bash, Dash, zsh, ksh, and sh

In Bash, and other Bourne shells, you can most easily accomplish it by doing something like this:

errvar=$((echo "err" 1>&2) 2>&1)

The echo part just means to echo “err” on stderr rather than stdout. You can put any command you need within the inner parenthesis. Note that this method will mix the output of stdout and stderr.

To avoid having the output get mixed, we can do something like the following:

 errvar=$((curl 2>&1 >/dev/null)


With fish, you set variables a bit differently. It took more than a few minutes to do the echo example I used before, so I decided on this example instead:

set errvar (ssh -o ConnectTimeout=10 300.300.300.300 2>&1)

fish doesn’t do command substitutions the same way Bash does, so we can have one fewer sets of parenthesis.

This should output ssh: Could not resolve hostname 300.300.300.300: Name or service not known on stderr, which will be redirected into the variable errvar.

The same method as Bourne shells can be used to pipe only stderr to the variable, with fish it will look like this:

set errvar (curl 2>&1 >/dev/null)

tcsh and csh

C shell doesn’t have the output redirection power of Bourne shells, sadly. To the best of my knowledge, it is impossible to only redirect stderr. Repeating my SSH example from the fish shell, you can accomplish the same with:

set errvar="`ssh -o ConnectTimeout=10 300.300.300.300 |& cat`"

Be warned that this will redirect all output streams, not just standard error. So, a command that has the output mixed (curl, for example) will also have it’s output redirected to the variable, potentially resulting in this:

All output streams were redirected to the variable, rather than just stderr.
All output streams were redirected to the variable.


oh is the youngest shell on this list. The first release was in 2011 and development has been pretty active since then. Like with tcsh, it’s redirect abilities are not that powerful. The best way to manage this is to redirect all output streams to a variable, which can be done like so:

define errvar = `(ssh -o ConnectTimeout=10 300.300.300.300 !| cat)

Closing Notes

I hope this helped you out! If there’s a shell I missed, if one of my examples is broken, or if you have any questions, feel free to leave a comment and I’ll do my best to address it.

About: Bailey Kasin

I build virtual environments and challenges for Cybersecurity students to complete as a way to gain experience before graduating and entering the workforce.

Leave a Reply

Your email address will not be published. Required fields are marked *