bash – Best Way to Detect if Software is Installed from a Script

bashstandardwhichzsh

I've been frustrated before with differences in output from the which command across different platforms (Linux vs. Solaris vx. OS X), with different shells possibly playing into the matter as well. type has been suggested as a better alternative, but how portable would that be?

In the past I've written functions which parse the output of which and handle the different use cases I've run into. They work across the machines I use, and so are okay for my personal scripts, but this seems terribly unreliable for software that I'm going to post somewhere for others to use.

To take just one possible example, suppose I have to detect from a script whether bash and zsh are available on a machine, and then run a command with zsh if it is present, and with bash if zsh is not and bash is of a sufficient version to not have a particular bug. Most of the rest of the script could be Bourne shell or Ruby or anything else, but this one particular thing must be done (AFAIK) with either zsh or a recent version of bash.

Can I count on type being available across platforms? Is there some other alternative to which which can easily and consistently answer the question of whether a particular piece of software is installed?

(If you want to also give ideas specifically related to the example I gave, that's great, but I'm mainly just asking about the general case: what is the most reliable way to find out if a particular thing is installed on a given machine?)

Best Answer

In the 21st century, especially if you're targeting machines that are likely to have bash or zsh, you can count on type being available. (It didn't exist in extremely old unices, as in, from the 1970s or early 1980s.) You can't count on its output meaning anything, but you can count on its returning 0 if there is a command by that name and nonzero otherwise.

which isn't standard and is unreliable in practice. type is the recommended alternative. whereis suffers from the same problems as which and is less common. whence is specific to ksh and zsh.

When that's possible, it would be more reliable to test the existence of a command and test whether its behavior looks reasonable. For example, test the presence of a suitable version of bash by running bash -c 'somecommand', e.g.

# Test for the `-v` operator (which appeared in bash 4.2)
if bash -c 'test -v HOME' 2>/dev/null; then …

Today you can count on almost everything in the Singe UNIX specification version 2 (except for exotic stuff like Fortran and SCCS, which are optional anyway). You can count on most of version 3, too, but this isn't completely implemented everywhere yet. Version 4 support is sketchier. If you're going to read these specs, I recommend reading version 3, which is a lot more readable and less ambiguous than version 2.

For examples as to how to detect system specificities, look at autoconf and at configure scripts of various software.

See also Resources for portable shell programming for more tips.

Related Question