How do I test to see if an application exists in $PATH?
Solution 1
Use type commandname
. This returns true if commandname
is anything executable: alias, function, built-in or external command (looked up in $PATH
). Alternatively, use command commandname
which returns true if commandname
is a built-in or external command (looked up in $PATH
).
exists () {
type "$1" >/dev/null 2>/dev/null
}
There are a few sh variants (definitely pre-POSIX; I know of /bin/sh
under OSF1 ≤3.x and some versions of the Almquist shell found in early NetBSD versions and a few 20th-century Linux distributions) where type
always returns 0 or doesn't exist. I don't think any systems shipped with these this millennium. If you ever encounter them, here's a function you can use to search in $PATH
manually:
exists () { (
IFS=:
for d in $PATH; do
if test -x "$d/$1"; then return 0; fi
done
return 1
) }
This function is generally useful if you want to exclude built-ins and functions and look up the name in $PATH
. Most shells have a built-in for this, command -v
, though it's a relatively recent addition to POSIX (still optional as of POSIX:2004). It's basically a programmer-friendly version of type
: it prints the full path for an executable in $PATH
, the bare name for a built-in or function, and an alias definition for an alias.
exists_in_path () {
case $(command -v -- "$1") in
/*) return 0;;
alias\ *) return 1;; # alias
*) return 1;; # built-in or function
esac
}
Ksh, bash and zsh also have type -p
to look up only executables in $PATH
. Note that in bash, the return status of type -p foo
is 0 if foo
is a built-in or function; if you want to test for an executable in $PATH
, you need to check that the output is not empty. type -p
is not in POSIX; for instance Debian's ash (which is /bin/sh
on Ubuntu) doesn't have it.
Solution 2
If you are only looking for external programs, you can also use which. Don't know how portable that is though.
Related videos on Youtube
xenoterracide
Former Linux System Administrator, now full time Java Software Engineer.
Updated on September 17, 2022Comments
-
xenoterracide almost 2 years
I'm trying to write all of my
sh
startup/env scripts to work with as much DRY and as much: "works on every *nix I clone it to", as possible. This means making sure that if I try to run code that's not there, that the code fails gracefully. To that end I need to be able to test if programs exist. I know how to test if a file exists, but I'm not sure how to test to see if an application is executable within the path. I'd rather use the $PATH, as some of these need to work on arch, ubuntu, and centos. Some might be installed in my homedir, on systems where I don't have root, others might not be installed, and others yet my be installed in system paths.-
Admin almost 12 yearsThis SO answer is the one I have bookmarked for such questions.
-
Admin over 3 years
-
-
Gilles 'SO- stop being evil' over 13 years@xenoterracide: Drop the brackets!
-
Steven D over 13 yearsI think you are looking for
if type $APP >/dev/null 2>/dev/null; then ...
You don't want the[]
. -
Steven D over 13 yearsBah, I knew I should have refreshed. Beaten by Gilles again!
-
Gilles 'SO- stop being evil' over 13 yearsIn theory, it's less portable than
type
orcommand
;which
is not in POSIX, for instance. In practice,which
does exist almost everywhere, but in some places (where it's implemented as a csh script) it uses a different path (due to a.cshrc
), which defeats the purpose. -
ephemient over 13 years
type -p
if you're specifically looking for a command in$PATH
(not aliases or functions or builtins). -
Gilles 'SO- stop being evil' over 13 years@ephemient:
type -p
isn't portable, and a bit strange in bash (see my edit). -
Admin about 2 years
type -P
in bash if specifically looking for a command in $PATH (not aliases or functions or builtins). Added in bash 2.05b. Admittedly, this isn't portable, which is what the OP wanted.