How do I find the last argument in a Bourne shell script?

How do I find the last argument in a Bourne shell script?

Answer by:
Martin Weitzel <@mikros.systemware.de:martin@mwtech.uucp>
Maarten Litmaath

If you are sure the number of arguments is at most 9, you can use:

eval last=\${$#}

In POSIX-compatible shells it works for ANY number of arguments.
The following works always too:

for last
do
:
done

This can be generalized as follows:

for i
do
third_last=$second_last
second_last=$last
last=$i
done

Now suppose you want to REMOVE the last argument from the list,
or REVERSE the argument list, or ACCESS the N-th argument
directly, whatever N may be. Here is a basis of how to do it,
using only built-in shell constructs, without creating subprocesses:

t0= u0= rest='1 2 3 4 5 6 7 8 9' argv=

for h in '' $rest
do
for t in "$t0" $rest
do
for u in $u0 $rest
do
case $# in
0)
break 3
esac
eval argv$h$t$u=\$1
argv="$argv \"\$argv$h$t$u\"" # (1)
shift
done
u0=0
done
t0=0
done

# now restore the arguments
eval set x "$argv" # (2)
shift

This example works for the first 999 arguments. Enough?
Take a good look at the lines marked (1) and (2) and convince
yourself that the original arguments are restored indeed, no
matter what funny characters they contain!

To find the N-th argument now you can use this:

eval argN=\$argv$N

To reverse the arguments the line marked (1) must be changed to:

argv="\"\$argv$h$t$u\" $argv"

How to remove the last argument is left as an exercise.

If you allow subprocesses as well, possibly executing nonbuilt-in
commands, the `argvN' variables can be set up more easily:

N=1

for i
do
eval argv$N=\$i
N=`expr $N + 1`
done

To reverse the arguments there is still a simpler method, that
even does not create subprocesses. This approach can also be
taken if you want to delete e.g. the last argument, but in that
case you cannot refer directly to the N-th argument any more,
because the `argvN' variables are set up in reverse order:

argv=

for i
do
eval argv$#=\$i
argv="\"\$argv$#\" $argv"
shift
done

eval set x "$argv"
shift



Home FAQ