They key is in using hash
or type
to see if a command is available. For example, the output of
1hash nano
will change based on whether nano
is installed or not. If nano is installed, you’ll get nothing. If nano
is not installed, you’ll get an error.
So, we check for an error to see if something is not installed.
1command -v foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
OR
1type foo >/dev/null 2>&1 || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
OR
1hash foo 2>/dev/null || { echo >&2 "I require foo but it's not installed. Aborting."; exit 1; }
Where bash
is your shell/hashbang, consistently use hash
(for commands) or type
(to consider built-ins & keywords).
When writing a POSIX script, use command -v
.
We can also use this in a function, like so:
1gnudate() {
2 if hash gdate 2>/dev/null; then
3 gdate "$@"
4 else
5 date "$@"
6 fi
7}
which
commandThe which
command tells you if a program is in the user’s path. Being in the path usually means it is installed.
1which homebrew
1 # bash - will print nothing if it's not found
2brew not found # zshell - will tell you not found
3brew: Command not found # csh
Please note that the which
command will tell you a program is installed only if it’s in the $PATH
. So in cases where you have brew
installed, but for some reason didn’t update the $PATH
then which brew will tell you homebrew not found
I have had this happen to me when i made the switch from Bash to Zshell. Since all my paths were in my old ~/.bash_profile
and are not in the new ~/.zshrc
, it’s telling me stuff is not installed when it actually is.
1➜ ~ git:(master) ✗ brew --version
2Homebrew 1.3.6
3Homebrew/homebrew-core (git revision fad42; last commit 2017-10-28)
4➜ ~ git:(master) ✗ which -s homebrew
5homebrew not found
6➜ ~ git:(master) ✗ which homebrew
7homebrew not found
command -v brew
is a better alternative to which brew