Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

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.

share|improve this question
    
This SO answer is the one I have bookmarked for such questions. –  jw013 Aug 29 '12 at 22:10

2 Answers 2

up vote 16 down vote accepted

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.

share|improve this answer
    
@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... –  xenoterracide Dec 19 '10 at 0:00
    
@xenoterracide: Drop the brackets! –  Gilles Dec 19 '10 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 '10 at 0:05
4  
Bah, I knew I should have refreshed. Beaten by Gilles again! –  Steven D Dec 19 '10 at 0:06
    
type -p if you're specifically looking for a command in $PATH (not aliases or functions or builtins). –  ephemient Jan 8 '11 at 6:34

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

share|improve this answer
3  
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. –  Gilles Dec 19 '10 at 13:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.