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's been stumping me.
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's been stumping me.
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
command
is POSIX compliant, see here for its specification: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/command.htmlNote:
type
is POSIX compliant, buttype -P
is not.Why not use Bash builtins if you can?
...
The
which
command might be useful. man whichIt returns 0 if the executable is found, 1 if it's not found or not executable:
Nice thing about which is that it figures out if the executable is available in the environment that which is run in - saves a few problems...
-Adam
If there is no external
type
command available (as taken for granted here), we can use POSIX compliantenv -i sh -c 'type cmd 1>/dev/null 2>&1'
:At least on Mac OS X 10.6.8 using Bash 4.2.24(2)
command -v ls
does not match a moved/bin/ls-temp
.Answer
POSIX compatible:
For
bash
specific environments:Explanation
Avoid
which
. Not only is it an external process you're launching for doing very little (meaning builtins likehash
,type
orcommand
are way cheaper), you can also rely on the builtins to actually do what you want, while the effects of external commands can easily vary from system to system.Why care?
which
that doesn't even set an exit status, meaning theif which foo
won't even work there and will always report thatfoo
exists, even if it doesn't (note that some POSIX shells appear to do this forhash
too).which
do custom and evil stuff like change the output or even hook into the package manager.So, don't use
which
. Instead use one of these:(Minor side-note: some will suggest
2>&-
is the same2>/dev/null
but shorter – this is untrue.2>&-
closes FD 2 which causes an error in the program when it tries to write to stderr, which is very different from successfully writing to it and discarding the output (and dangerous!))If your hash bang is
/bin/sh
then you should care about what POSIX says.type
andhash
's exit codes aren't terribly well defined by POSIX, andhash
is seen to exit successfully when the command doesn't exist (haven't seen this withtype
yet).command
's exit status is well defined by POSIX, so that one is probably the safest to use.If your script uses
bash
though, POSIX rules don't really matter anymore and bothtype
andhash
become perfectly safe to use.type
now has a-P
to search just thePATH
andhash
has the side-effect that the command's location will be hashed (for faster lookup next time you use it), which is usually a good thing since you probably check for its existence in order to actually use it.As a simple example, here's a function that runs
gdate
if it exists, otherwisedate
:It depends whether you want to know whether it exists in one of the directories in the
$PATH
variable or whether you know the absolute location of it. If you want to know if it is in the$PATH
variable, useotherwise use
The redirection to
/dev/null/
in the first example suppresses the output of thewhich
program.