This question already has answers here:
Closed 3 years ago.
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?
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 $?
You're using zsh's &>
operator, which redirects stderr and stdout. The way you've used it suggests you meant ... > /dev/null 2>&1
instead.
I would do this as:
$ cc=$( type -P clang gcc othercc | head -n 1 )
$ echo $cc
/usr/bin/clang
Use this:
which gcc >& /dev/null && echo gcc || echo clang
Also you can use this:
[[ $(which gcc) ]] && echo gcc || echo clang # prints gcc
[[ $(which clang) ]] && echo gcc || echo clang # prints clang
This works because in [[ ]]
empty strings are falsey.