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?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this communityFor 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?
Assuming you can change the the script, you should consider using optional parameters (options) instead of required parameters (arguments).
If you have each of the first 7 seven parameters as options, and have them default to the empty string then you could just do:
./foo bar
If you use a POSIX-compatible shell you can use the getopts
utility, or the program getopt
. bash
- like most shells - offers getopts
as a built-in. Either way is easier than rolling your own command-line parser.
Unless you implement something like the last X non-option arguments are the values for the last Y arguments and X-Y option arguments you have to provide option strings before each of the 7 (now empty) strings if you want to set any of those. This however is not common practise, normally an option is always an option and an argument an argument, and the order of option "insertion" is free.
+1
for getopt(s)
. Positional parameters are a sad time, and should be avoided.
Sep 7, 2014 at 15:04
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
$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 *
$eight = file008
There we only see the eighth operand, but there are 101 of them globbed from my test directory.