views:

383

answers:

3

I want to be able to tell if a command exists on any POSIX system from a shell script.

On Linux, I can do the following:

if which <command>; then
   ...snip...
fi

However, Solaris and MacOS which do not give an exit failure code when the command does not exist, they just print an error message to STDOUT.

Also, I recently discovered that the which command itself is not POSIX (see http://www.opengroup.org/onlinepubs/009695399/utilities/)

Any ideas?

A: 

You could read the stdout/stderr of "which" into a variable or an array (using backticks) rather than checking for an exit code.

If the system does not have a "which" or "where" command, you could also grab the contents of the $PATH variable, then loop over all the directories and search for the given executable. That's essentially what which does (although it might use some caching/optimization of $PATH results).

Andy White
The problem is, that even on systems that *have* which, I am not guarenteed there will even *be* any output... I guess I could just check to see that it doesn't "look like a path"...
singpolyma
Ah, [ -x "`which aeiei`" ] could work... again, assuming which exists...
singpolyma
A: 

POSIX does say, “If a command is not found, the exit status shall be 127.” So you could do

<command>
if [ "${?}" = 127 ]; then
   <handle not found>
fi

When writing shell scripts, it’s often permissible to require a bash shell (#!/bin/bash), because without arrays it’s pretty much impossible to handle arguments and/or filenames with spaces correctly. In that case, the bash builtin type -p is equivalent to which, and because it is builtin, it is portable.

andrew
Type without -p is POSIX, but POSIX does not guarentee that it interprets the command not existing as an error.
singpolyma
Bash is an extra on many systems. Trying to find if things are supported using a non-standard shell isn't too good.
dwc
On Ubuntu, they have tried to switch from bash to dash for as many scripts as possible (especially during startup) because it is smaller and faster to launch. And the BSDs don't ship with bash in their base install. Nor do most System V based unixes.
Brian Campbell
+3  A: 

command -v is a POSIX specified command that does what which does.

It is defined to to return >0 when the command is not found or an error occurs.

singpolyma