tags:

views:

21

answers:

3

Like most makefiles, I have some bash scripts that use variables for executables. For example, $mysql_exec for /usr/bin/mysql. I would like to be able to say something like:

mysql_exec=mysql

to use $PATH or

mysql_exec=/usr/bin/mysql

to get an absolute location without $PATH. I also want to check to see if the executable is valid using something like this:

if [ ! -x $mysql_exec ] ...

However, this command:

if [ ! -x "mysql" ]; then print "oh oh"; fi

Actually prints "oh oh", even though mysql is in my $PATH. From the command-line, typing mysql has the same effect as typing /usr/bin/mysql. So, how do I get bash really check to see if $mysql_exec is an executable ($PATH and all)?

+2  A: 

which is a small program that checks $PATH for a program specified as an argument:

$ which mysql
/usr/bin/mysql

Another useful utility (that isn't installed on all systems but is included in GNU CoreUtils) is readlink. readlink can give you back a full and absolute path, without symlinks. For example:

$ cd ~me/bin
$ ln -s `which mysql` mysupersql
$ readlink -f mysupersql
/usr/bin/mysql      

I often use a combination of both so I know that the path is both absolute and not a symlink:

mysql_exec=$(readlink -f `which mysql`)
if [ ! -x "$mysql_exec" ] ; then
    ...
Kaleb Pederson
A: 

To add to Kaleb's answer, you an also check if the file is a symlink using if [-L $file] and follow that symlink if you can't install readlink. The rest of the check though remains as the way Kaleb mentioned.

Gangadhar
+2  A: 

In Bash, you can use the built-in type -P to force a resolution against the PATH or type -p to show the path only if there's no alias or function by that name. Using type avoids calling an external such as which.

Something like this may do what you're looking for:

[ -x "$(type -p "$mysql_exec")" ]

whether you use

mysql_exec=mysql

or

mysql_exec=/usr/bin/mysql
Dennis Williamson
Very nice Dennis. Thanks for the `type` tip!
Kaleb Pederson