Shell – When running a shell script, is it possible to pass specific positional parameters without having to enter them all in order

parametershell-script

For example, if I have script ./foo that takes 10 parameters, and I only want to pass the 8th parameter. The only way I know how to do this currently is:

./foo '' '' '' '' '' '' '' 'bar'

Is there an easier/better way?

Best Answer

Another way to do this thing is to name the parameter you want to declare and then do so:

{   cat >./foo 
    chmod +x ./foo
    eight=declared ./foo
    eight=declared_and_preferred \
        ./foo 1 2 3 4 5 6 7 8
    ./foo 1 2 3 4 5 6 7 8
    ./foo
} <<\SCRIPT
#!/usr/bin/sh
: ${eight:=${8:-some_default}}
printf '$eight = %s\n' "$eight"
#END
SCRIPT

OUTPUT

$eight = declared
$eight = declared_and_preferred
$eight = 8
$eight = some_default

In the above example the explicitly declared environment variable is preferred to the command-line argument, but the command-line argument is used when the environment variable is either empty or unset. When both the 8th positional and the environment variable $eight are empty or unset the default value some_default is assigned to $eight. In either case the : can be removed from the :- or := statements if empty should be an acceptable value.

The variable $eight could as well have been set like:

printf '$eight = %s\n' "${eight:=${8:-some_default}}"

... and the previous line omitted entirely but I wanted to demonstrate that declaring a variable in that way does result in a persistent value, and so I did it in two commands. Either way $eight is set to the final value of that compound parameter expansion.

getopts - for robust scripts - often is the best way to handle command options. Positional parameters, on the other hand, are almost always the most simple means of robustly handling operands in a script.

For example:

touch file$(seq -ws\ file 100)
./foo *

OUTPUT

$eight = file008

There we only see the eighth operand, but there are 101 of them globbed from my test directory.