next up previous contents
Next: A Real Life Example Up: Bourne shell Previous: Bourne shell debug

   
Indirect Commands

First of all we define the meaning of indirect command pointing out that this is not a Unix term but it represents a very common Unix practice. An indirect command is a command given using another command of which the command to execute is either an explicit argument or a shell variable.

The informations given in this section refer to any Unix shell provided that variables are defined according to the shell syntax. Here we want to draw the reader's attention on the many different ways Unix allows to achieve the same operation. It is important that the Unix programmer understands well the several syntax choises when implementing complex scripts and is aware that a mistake can produce very strange or even catastrophic results.

Let us start with a very simple operation, the list of files in the working directory. The same result can be achieved in any of the following ways:

1.
use the builtin echo
2.
use program ls
3.
combine a shell variable with either echo or the builtin eval
As first step we inquire the type of the shell elements we are going to use:

$ type echo eval ls
echo is a shell builtin
eval is a shell builtin
ls is /usr/bin/ls
$
Then we try echo and ls to see the output produced by the two commands:

$ echo *
args bdb cmd.dbs elif excase exists inp loop shodate shodef
$ ls
args     cmd.dbs  excase   inp      shodate
bdb      elif     exists   loop     shodef
Both commands produce a list of files with slightly different print format. At this point we want to show the different results produced using a shell variable as argument of either echo or eval. We define the local variable jj and apply it both to echo and eval using the same syntax in both cases.

$ jj=ls
$ echo jj
jj
$ echo $jj
ls
$ echo `$jj`
args bdb cmd.dbs elif excase exists inp loop shodate shodef
$ #----------------------------------------------------------
$ eval jj
jj: not found
$ eval $jj
args     cmd.dbs  excase   inp      shodate
bdb      elif     exists   loop     shodef
$ eval `$jj`
./args: IFS: not found
Proc ./args demo for args and shift
Full args: bdb cmd.dbs elif excase exists inp loop shodate shodef
Type first 3 args
bdb cmd.dbs elif
Type remaining args 4 and 5
excase exists

In the above example jj is assigned the value of ls. The first echo command lists the word jj, as the variable jj is not prefixed with $ for variable translation. The second echo command lists the value of jj. In the third example jj is embedded in backquotes, therefore echo executes ls as an indirect command and produces the wanted output. Then we repeat the same operation using eval. As eval tries to concatenate and recursively execute commands, at first invocation eval writes a message as jj is not a command, the second eval acts on the value of jj that is prefixed by $ and executes ls as an indirect command, producing the wanted result. The third eval executes as indirect command args, the first file in the file list and uses the other file names in the list as arguments of args producing unwanted and wrong results as shown by the output of the example.

In this example no damage is done as procedure args is a demo of the shift operation and it only prints a selected choice of input arguments, but try to image what might happen if the first file in the list was designed to remove files. Therefore great care must be exercised to avoid serious damages using eval with the wrong arguments.


next up previous contents
Next: A Real Life Example Up: Bourne shell Previous: Bourne shell debug
Marisa Luvisetto
2001-02-05