Here's the concrete task I'm trying to accomplish. zsh behaves the way I like
$ zsh
$ which clang > /dev/null 2&>1 && echo clang || echo gcc
clang
$ which doesntexist > /dev/null 2&>1 && echo doesntexist || echo gcc
gcc
But, in bash:
$ bash
$ which clang > /dev/null 2&>1 && echo clang || echo gcc
gcc
Here's the general case:
$ which clang > /dev/null 2&>1; echo $?
1
$ which clang; echo $?
/usr/bin/clang
0
There's something wrong with how I'm redirecting output. What's the right way?
Understanding the concept of redirections and file descriptors is very important when working on the command line. To redirect stderr and stdout , use the 2>&1 or &> constructs.
Discussion. &> or >& is a shortcut that simply sends both STDOUT and STDERR to the same place—exactly what we want to do. In the third example, the 1 appears to be used as the target of the redirection, but the >& says to interpret the 1 as a file descriptor instead of a filename.
I think you're redirecting the wrong way:
which clang > /dev/null 2&>1; echo $?
Should be
which clang > /dev/null 2>&1; echo $?
It's probably how either shells allow the former method. In bash it's not the right way. Bash would interpret it instead like:
which clang >/dev/null 2 &>1; echo $?
In which 2
is added as an argument.
You can verify that by creating a function like
e() { echo "$@" >e.log; }
And call it as:
e 1 >/dev/null 2&>/dev/null
And you would get 1 2
in e.log.
In bash it's also simpler if you call your command like this:
which clang &>/dev/null; echo $?
Also rather than calling an external binary like which
, use type -P
instead. No need to redirect stderr output too.
type -P clang >/dev/null; echo $?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With