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.


2 Answers 2


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 () { (
    for d in $PATH; do
      if test -x "$d/$1"; then return 0; fi
    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

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.

  • @gilles, will this (or something similar) if [ type keychain ]; then not work? I get error /home/xenoterracide/.zshrc:84: parse error: condition expected: type I suppose I could write the function exists... I just thought this might be simpler in a sense... Dec 19, 2010 at 0:00
  • @xenoterracide: Drop the brackets! Dec 19, 2010 at 0:03
  • I think you are looking for if type $APP >/dev/null 2>/dev/null; then ... You don't want the [].
    – Steven D
    Dec 19, 2010 at 0:05
  • 4
    Bah, I knew I should have refreshed. Beaten by Gilles again!
    – Steven D
    Dec 19, 2010 at 0:06
  • type -p if you're specifically looking for a command in $PATH (not aliases or functions or builtins).
    – ephemient
    Jan 8, 2011 at 6:34

If you are only looking for external programs, you can also use which. Don't know how portable that is though.

  • 5
    In theory, it's less portable than type or command; 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. Dec 19, 2010 at 13:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .