I noticed different .sh
scripts for homebrew which check whether it's installed.
One uses this syntax:
if test ! $(which brew); then
The other uses this syntax:
if ! which brew > /dev/null; then
I get that they are both checking the exit code for which brew
, but I'm curious as to whether there are other differences between them. To me, the former is clearer, and I would assume (maybe incorrectly) more efficient since it doesn't have to redirect any output.
Also, why does the second actually execute which brew
, regardless of whether the output is sent to /dev/null
or not? Just how shell works?
Best Answer
The first is a clumsy hack, the second is a common mistake.
These two tests do something completely different, which happens to produce the same outcome.
This tests whether the output of
which brew
is empty.brew
is on the search path, thenwhich brew
produces a word of output, so thetest
command receives two arguments:!
and the path tobrew
. Whentest
has two arguments, the first of which is!
, it returns true if the second argument is empty (which isn't the case here) and false otherwise.brew
isn't on the search path, then the output ofwhich brew
is empty, so thetest
command receives a single argument which is!
, sotest
returns true.Note that this command will produce an error message and a failure status if the path to
brew
contains whitespace, because that's what an unquoted command substitution means. It so happens that a failure status was the desired outcome here, so this works in a roundabout way.This command does not test the exit code of
which brew
. The exit code is ignored.This is the straightforward way to test if
which brew
succeeds. It doesn't depend on anything brittle exceptwhich
itself.which brew
is always called in both cases. Why would it matter that the output is redirected to/dev/null
? “Hide this command's output” does not mean “don't run this command”.The proper way to test if
brew
is not available on the command search path isSee Why not use "which"? What to use then?