Bash Shell Find Out If A Command Exists On UNIX / Linux System ($PATH) OR Not

by on April 6, 2010 · 6 comments· LAST UPDATED April 6, 2010

in , ,

I want find out if a command exists on UNIX from a bash shell script. If command does not exists in $PATH, then I would like to display an error message on screen. How do I find out if a command exists on Posix system or not?

You can use the following commands:

  1. command command - You can execute a simple command or display information about commands with the command called command. This is recommend for all Posix systems.
  2. type command - This is recommend for bash user. The -P option force a PATH search for each COMMAND NAME, even if it is an alias, builtin, or function, and returns the name of the disk file that would be executed.

Posix Command Example

The syntax is as follows:
command -v command1 >/dev/null && echo "command1 Found In \$PATH" || echo "command1 Not Found in \$PATH"

#!/bin/bash
# POSIX command lookup example
CMDS="tar /usr/bin/mysqldump /path/to/other/command"
 
for i in $CMDS
do
        # command -v will return >0 when the $i is not found
	command -v $i >/dev/null && continue || { echo "$i command not found."; exit 1; }
done
 
# add rest of the script as we found all bins in $PATH
echo "Starting backup...."
 

type -P command Example

The syntax is as follows:
type -P command1 &>/dev/null && echo "Found" || echo "Not Found"
Here is a sample script:

#!/bin/bash
# Use Bash builtin called type to determine whether a command exists or not
 
# Use full path if possible...
CMDS="tar /usr/bin/mysqldump ssh rsync"
 
for i in $CMDS
do
	type -P $i &>/dev/null  && continue  || { echo "$i command not found."; exit 1; }
 
# Add rest of the script as we found all bins in $PATH
echo "Starting backup...."
/bin/tar ....
 

You can use the exit status with which command as follows too:

which tar1 &>/dev/null
[ $? -eq 0 ] || echo "tar1 command not found."

I strongly recommend using full path for security reason for all sys admin activities. In this example, I've full path defined in /usr/local/nixcraft/redhat.paths.ini file:

_path_php_cgi="/usr/bin/php-cgi"
_path_chroot="/usr/sbin/chroot"
_path_lighttpd="/usr/sbin/lighttpd"
_path_mknod="/bin/mknod"
_path_spawn_fcgi="/usr/bin/spawn-fcgi"
_path_cp="/bin/cp"
_path_mv="/bin/mv"

You can use the following code to verify that all path exists and than call those hard coded part later on:

#!/bin/bash
source  /usr/local/nixcraft/redhat.paths.ini
# get those path vars
paths=$(set | grep ^_path_*)
 
# verify those paths
for p in $paths
do
	type -P ${p##*=} &>/dev/null || { echo  "${p##*=} not found"; exit 1; }
done
 
# Alright, we got all binaries 
echo "Starting chroot() for ${_path_lighttpd}..."
 
 

Here is a sample script which use type -P:

#!/bin/bash
RRDTOOL=/usr/bin/rrdtool
OUTDIR=/var/www/html/lighttpd.rrd
INFILE=/home/lighttpd/rrd
OUTPRE=lighttpd-traffic
WIDTH=400
HEIGHT=100
 
# make sure rrdtool exists; else die with an error message
type -P $RRDTOOL &>/dev/null || { echo "$RRDTOOL not found. Set \$RRDTOOL in $0"; exit 1; }
 
# make sure dir exits; else create it
[ -d $OUTDIR ] || mkdir -p $OUTDIR
 
# make sure input file exits; else die with an error message
[ -f $INFILE ] || { echo "$INFILE input file not found. set \$INFILE in $0"; exit 2; }
 
DISP="-v bytes --title TrafficWebserver \
        DEF:binraw=$INFILE:InOctets:AVERAGE \
        DEF:binmaxraw=$INFILE:InOctets:MAX \
        DEF:binminraw=$INFILE:InOctets:MIN \
        DEF:bout=$INFILE:OutOctets:AVERAGE \
        DEF:boutmax=$INFILE:OutOctets:MAX \
        DEF:boutmin=$INFILE:OutOctets:MIN \
        CDEF:bin=binraw,-1,* \
        CDEF:binmax=binmaxraw,-1,* \
        CDEF:binmin=binminraw,-1,* \
        CDEF:binminmax=binmaxraw,binminraw,- \
        CDEF:boutminmax=boutmax,boutmin,- \
        AREA:binmin#ffffff: \
        STACK:binmax#f00000: \
        LINE1:binmin#a0a0a0: \
        LINE1:binmax#a0a0a0: \
        LINE2:bin#efb71d:incoming \
        GPRINT:bin:MIN:%.2lf \
        GPRINT:bin:AVERAGE:%.2lf \
        GPRINT:bin:MAX:%.2lf \
        AREA:boutmin#ffffff: \
        STACK:boutminmax#00f000: \
        LINE1:boutmin#a0a0a0: \
        LINE1:boutmax#a0a0a0: \
        LINE2:bout#a0a735:outgoing \
        GPRINT:bout:MIN:%.2lf \
        GPRINT:bout:AVERAGE:%.2lf \
        GPRINT:bout:MAX:%.2lf \
        "
 
$RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP -w $WIDTH -h $HEIGHT
$RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP -w $WIDTH -h $HEIGHT
$RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP -w $WIDTH -h $HEIGHT
 
OUTPRE=lighttpd-requests
 
DISP="-v req --title RequestsperSecond -u 1 \
        DEF:req=$INFILE:Requests:AVERAGE \
        DEF:reqmax=$INFILE:Requests:MAX \
        DEF:reqmin=$INFILE:Requests:MIN \
        CDEF:reqminmax=reqmax,reqmin,- \
        AREA:reqmin#ffffff: \
        STACK:reqminmax#00f000: \
        LINE1:reqmin#a0a0a0: \
        LINE1:reqmax#a0a0a0: \
        LINE2:req#00a735:requests"
 
$RRDTOOL graph $OUTDIR/$OUTPRE-hour.png -a PNG --start -14400 $DISP -w $WIDTH -h $HEIGHT
$RRDTOOL graph $OUTDIR/$OUTPRE-day.png -a PNG --start -86400 $DISP -w $WIDTH -h $HEIGHT
$RRDTOOL graph $OUTDIR/$OUTPRE-month.png -a PNG --start -2592000 $DISP -w $WIDTH -h $HEIGHT

Further readings:

Our Linux shell scripting tutorial and the following man pages:
man bash
man ksh
help type
help command

TwitterFacebookGoogle+PDF versionFound an error/typo on this page? Help us!

{ 6 comments… read them below or add one }

1 tonf April 7, 2010 at 8:38 pm

use “which”
like “which somecommand”
where the result will be blank if it does not exist or the full path of the command if it does

Reply

2 Clay May 4, 2010 at 8:03 pm

Using “which” won’t show if the command that will be executed is an alias. “type” will show if there’s an alias.

Reply

3 darko September 17, 2010 at 9:43 pm

According to The Open Group Base Specifications, `command -v` is not completely portable and `type -P` is not portable either:

type,
command

Reply

4 Spam Assasin December 9, 2011 at 3:59 pm

I have aliased ll=”ls -l” and it is there in $PATH. Yet “type -P” doesn’t show it. So @tonf is correct, which is simpler and easier to remember.

Reply

5 Daniel Hahler July 21, 2014 at 12:01 am

FWIW: `type -P` does not work with zsh:

% type -P mountpoint
zsh: bad option: -P

And “command” is not available with “ash”, a minimal shell used with BusyBox v1.16.1 (e.g. on a Synology Diskstation).

Reply

6 Daniel Hahler July 21, 2014 at 12:07 am

`type -P` appears to be specific to Bash.

`type -p` (lowercase “p”) works with bash, busybox/ash and zsh, and is similar to `-P`.

Reply

Leave a Comment

Tagged as: , , , , , , , , , , ,

Previous Faq:

Next Faq: