Re: Absolute pathnames to commands in shell scripts

From: Ed Morton (morton_at_lsupcaemnt.com)
Date: 01/29/04


Date: Thu, 29 Jan 2004 09:35:13 -0600


Clyde Ingram wrote:

> What are readers views of shell scripts calling other programs by
> specifying absolute pathname?
>
> Some alternative choices I am aware of, to call commands such as:
>
> /bin/ls
> /opt/myapps/mybin/myprog
>
> are:
>
>
> 1. Put all directories in the PATH
>
> PATH=/bin:/usr/bin:/opt/myapps/mybin
>
> ls /a/b/c/d
> myprog -a aaa -b bbb

I usually do that for scripts that only I use since I can always easily
debug problems in my own scripts and this is a quick and easy way to get
at where the tools should be.

<snip>
> 2. Define all invoked commands at the top
>
> LS="/bin/ls"
> MYPROG="/opt/myapps/mybin/myprog"
>
> $LS /a/b/c/d
> $MYPROG -a aaa -b bbb
>
> I think this is widely practiced.
> An advantage is that you can test for the existance of executables,
> before trying to call them:

Exactly. I do this in scripts that many people are going to use since
they need to be more robust and provide good error detection and error
messages.

The naming convention that most people use is to reserve all-upper-case
names for exported variables, so your variable names should really be
something like:

     ls="/bin/ls"
     myprog="/opt/myapps/mybin/myprog"

     $ls /a/b/c/d
     $myprog -a aaa -b bbb

but that introduces a potential problem because if you forget to put the
"$" in when using those variables, e.g.:

     ls="/bin/ls"
     myprog="/opt/myapps/mybin/myprog"

     ls /a/b/c/d
     myprog -a aaa -b bbb

then you find yourself either calling the wrong versions of "ls" and
"myprog" or thenm being inecplicably missing. Even worse, you may
initially be calling the correct versions and it's 3 years down the road
before the wrong version appears earlier in your PATH and then you have
to try to fifure out what suddenly went wrong in your previously working
script when you didn't change the script!

To get around this, you need to adopt a different naming convention for
your non-exported variables. I always prefix mine with underscore, e.g.:

     _ls="/bin/ls"
     _myprog="/opt/myapps/mybin/myprog"

     $_ls /a/b/c/d
     $_myprog -a aaa -b bbb

but you could come up with something else if you don't like that.

<snip>
> 3. Spell out the full pathname
>
> /bin/ls /a/b/c/d
> /opt/myapps/mybin/myprog -a aaa -b bbb
>
> This avoids the ugliness of variables like $LS, but having to spell
> out the (right) pathname for every command (and know which ones are
> built-ins, so have no pathname) seems plain awkward.

Don't do that since there will be times when you want to call the same
command in multiple places in one script so then you'd be duplicating
the path information and making the script harder to maintain.

Another option you didn't mention is to create a variable for the path
to each tool, e.g.:

     lsBin="/bin"
     myprogBin="/opt/myapps/mybin"

     ${lsBin}/ls /a/b/c/d
     ${myprogBin}/myprog -a aaa -b bbb

I wouldn't do that myself since it can also result in some duplication
and it'd be easy to forget the bin prefix and end up calling the wrong tool.

A final option would be to create a function for each external tool, e.g.

        function ls { /bin/ls "$@"; }
        function myprog { /opt/myapps/mybin/myprog "$@"; }

        ls /a/b/c/d
        myprog -a aaa -b bbb

and then your only potential problem would be if you forgot to create a
function for the tool, then you'd just be calling whichever version is
first in your PATH.

Probably the best solution overall is to define a meaningful variable
for the path to the bin of each cluster of tools you use and then use
that in the function definitions so that if, say, all of your printer
management tools moved to a different bin, you'd just change the
variable, e.g.:

        prtBin="/usr/spool/bin"
        dataBin="/home/bill/bin"
        calendarBin="/home/bill/bin"

        function prt { ${prtBin}/prt "$@"; }
        function prtstat { ${prtBin}/prtstat "$@"; }
        function prtcancel { ${prtBin}/prtcancel "$@"; }
        function dump { ${dataBin}/dump "$@"; }
        function delete { ${dataBin}/delete "$@"; }
        function agenda { ${calendarBin}/agenda "$@"; }

> A separate issue is whether production scipts should inherit the PATH
> from their (possibly uncontrolled) environment, or nail it down,
> either explicitly like in choice 1, or implicitly as in:
>
> . /opt/myapps/mybin/myenv
>
> (which presumably defines PATH for any caller).

I tend to just inherit the callers PATH so I can take advantage of the
system administrators having set some default tool dirs. I could could
see not wanting to do that for some applications though.

        Ed.



Relevant Pages

  • =?ISO-8859-1?Q?New_System_Command_Script_Facility?=
    ... I'm currently finished writing a new replacement command script processor ... (at least that RACF thinks so, and better support for non-RACF sites). ... The IF-type commands now have ELSE processing ... non-scroll highlighted console message and BEEP until a specific JOB or TASK ...
    (bit.listserv.ibm-main)
  • Re: Command Line Interface
    ... >> should accept system commands only for an administrator. ... >> how should I supress the bash shell and launch my custom CLI ... > The script could run in a restricted shell and offer a menu of ... account, and either 1) change account password, 2) ...
    (comp.os.linux.misc)
  • Net::Telnet and SMTP
    ... I'm trying to send a sequence of commands and then log both the ... I've included the script and a sample text file (that feeds the scripts ... sub processfile { ... #Try a short delay between sending command and reading output ...
    (comp.lang.perl.misc)
  • Re: [opensuse] Need some help with a script
    ... Need some help with a script ... arcane and tortured hypothetical scenarios beggar belief. ... Without dot in path, they can't. ... generally ensures somehow that the various commands ...
    (SuSE)
  • Re: Creative ways to time scripts?
    ... commands, but commands that also don't do anything. ... The script could be for either. ... Either in a single program or systemwide (in Windows of ...
    (microsoft.public.scripting.vbscript)