Differences between revisions 5 and 6
Revision 5 as of 2007-05-13 15:37:29
Size: 1659
Editor: GreyCat
Comment: clean-up
Revision 6 as of 2007-10-09 19:39:03
Size: 1871
Editor: JariAalto
Comment: which : change to use verb "may". E.g. under Solaris, which does set proper exit code and write message to sderr. New Which() function
Deletions are marked like this. Additions are marked like this.
Line 14: Line 14:
If these builtins are not available (because you're in a Bourne shell, or whatever), then you may have to rely on the external command {{{which}}} (which is often a csh script, although sometimes a compiled binary). Unfortunately, {{{which}}} does ''not'' set a useful exit code (on any system but GNU/Linux) -- and it doesn't even write errors to stderr! Therefore, one must parse its output. If these builtins are not available (because you're in a Bourne shell, or whatever), then you may have to rely on the external command {{{which}}} (which is often a csh script, although sometimes a compiled binary). Unfortunately, {{{which}}} may no set a useful ''exit'' ''code'' on systems other than GNU/Linux -- and it may not even write errors to stderr. In those cases, one must parse its output.
Line 18: Line 18:
# Backticks here because we're assuming a legacy Bourne shell.
x=`LC_ALL=C which qwerty 2>&1`
case "$x" in
  no\ *\ in\ *) echo qwerty does not exist;;
  *Command\ not\ found.) echo qwerty does not exist;;
  '') echo qwerty does not exist;;
  *) echo qwerty exists;;
esac
# Backticks + unset (no "local" used for variable); assume a legacy Bourne shell.
function Which()
{
    [ "$1" ] || return 1 # Require ARG

    tmpval=`LC_ALL=C which $1 2>&1`

    case "$tmpval" in
      *no\ *\ in\ *) tmpval="" ;;
      *not\ found*) tmpval="" ;;
      '') tmpval="" ;;
    esac

    if [ "$tmpval" ]; then
        echo $tmpval
        unset tmpval # prevent variable leak from function
        return 0
    else
        unset tmpval
        return 1
    fi
}

Which which

Anchor(faq81)

How can I determine whether a command exists anywhere in my PATH?

In BASH, there are a couple builtins that are suitable for this purpose: hash and type. Here's an example using hash:

if hash qwerty 2>/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

If these builtins are not available (because you're in a Bourne shell, or whatever), then you may have to rely on the external command which (which is often a csh script, although sometimes a compiled binary). Unfortunately, which may no set a useful exit code on systems other than GNU/Linux -- and it may not even write errors to stderr. In those cases, one must parse its output.

# Last resort -- using which(1)
# Backticks + unset (no "local" used for variable); assume a legacy Bourne shell.
function Which()
{
    [ "$1" ] || return 1     # Require ARG

    tmpval=`LC_ALL=C which $1 2>&1`

    case "$tmpval" in
      *no\ *\ in\ *) tmpval="" ;;
      *not\ found*)  tmpval="" ;;
      '')            tmpval="" ;;
    esac

    if [ "$tmpval" ]; then
        echo $tmpval
        unset tmpval    # prevent variable leak from function
        return 0
    else
        unset tmpval
        return 1
    fi
}

Which which

Note that its output is not consistent across platforms. On HP-UX, for example, it prints no qwerty in /path /path /path ...; on OpenBSD, it prints qwerty: Command not found.; on Debian and SuSE, it prints nothing at all; and on Gentoo, it actually prints something to stderr.

# Another easy way that works only on gnu:
if ! which qwerty >/dev/null 2>&1; then
  echo "$0: install qwerty first"
  exit 1
fi

(Although, on a GNU system, one would generally prefer to use one of the Bash builtins instead.)

BashFAQ/081 (last edited 2023-05-22 10:02:19 by emanuele6)