How would I validate that a program exists, in a way that will either return an error and exit, or continue with the script?
It seems like it should be easy, but it\
To use hash
, as @lhunath suggests, in a Bash script:
hash foo &> /dev/null
if [ $? -eq 1 ]; then
echo >&2 "foo not found."
fi
This script runs hash
and then checks if the exit code of the most recent command, the value stored in $?
, is equal to 1
. If hash
doesn't find foo
, the exit code will be 1
. If foo
is present, the exit code will be 0
.
&> /dev/null
redirects standard error and standard output from hash
so that it doesn't appear onscreen and echo >&2
writes the message to standard error.
Check for multiple dependencies and inform status to end users
for cmd in latex pandoc; do
printf '%-10s' "$cmd"
if hash "$cmd" 2>/dev/null; then
echo OK
else
echo missing
fi
done
Sample output:
latex OK
pandoc missing
Adjust the 10
to the maximum command length. It is not automatic, because I don't see a non-verbose POSIX way to do it:
How can I align the columns of a space separated table in Bash?
Check if some apt
packages are installed with dpkg -s
and install them otherwise.
See: Check if an apt-get package is installed and then install it if it's not on Linux
It was previously mentioned at: How can I check if a program exists from a Bash script?
I had to check if Git was installed as part of deploying our CI server. My final Bash script was as follows (Ubuntu server):
if ! builtin type -p git &>/dev/null; then
sudo apt-get -y install git-core
fi
I agree with lhunath to discourage use of which
, and his solution is perfectly valid for Bash users. However, to be more portable, command -v
shall be used instead:
$ command -v foo >/dev/null 2>&1 || { echo "I require foo but it's not installed. Aborting." >&2; exit 1; }
Command command
is POSIX compliant. See here for its specification: command - execute a simple command
Note: type
is POSIX compliant, but type -P
is not.
To mimic Bash's type -P cmd
, we can use the POSIX compliant env -i type cmd 1>/dev/null 2>&1
.
man env
# "The option '-i' causes env to completely ignore the environment it inherits."
# In other words, there are no aliases or functions to be looked up by the type command.
ls() { echo 'Hello, world!'; }
ls
type ls
env -i type ls
cmd=ls
cmd=lsx
env -i type $cmd 1>/dev/null 2>&1 || { echo "$cmd not found"; exit 1; }
The hash-variant has one pitfall: On the command line you can for example type in
one_folder/process
to have process executed. For this the parent folder of one_folder must be in $PATH. But when you try to hash this command, it will always succeed:
hash one_folder/process; echo $? # will always output '0'