Optional arguments after or before the mandatory arguments?
Solution 1
If you're fine with the optional arguments being at the end, you can just do this:
foo=$1
bar=$2
baz=${3:-default value}
That will store the first two arguments in $foo
and $bar
. If a third argument was provided, it will be stored in $baz
; otherwise it will default to default value
. You can also just check if the third variable is empty:
if [ -z "$3" ]; then
# Code for the case that the user didn't pass a third argument
fi
If you want the defaults at the beginning, the easiest way is probably to check the number of arguments passed to the script, which is stored in $#
. For example:
case $# in
2)
# Put commands here for when the user passes two arguments
# Could just be setting variables like above, or anything else you need
;;
3)
# Put commands here for when the user passes three arguments
;;
*)
echo "Wrong number of arguments passed"
exit 1;;
esac
Switching on $#
will work fine for either case, if you want error checking. If your script uses getopt-style arguments like the cut
example, you could use that; see this Stack Overflow question for more information
Solution 2
There are two different concepts: mandatory vs optional arguments, and options vs operands. Options are arguments that start with -
, operands are arguments that don't start with -
and aren't the argument of an option. Options are identified by their name and can normally be in any order. Operands are identified by their position. So in
someprogram -a -z -c foo bar
there are three options -a
, -c
and -z
, and there are two operands, the first being foo
and the second being bar
.
Options normally go before operands. GNU programs tend not to care about the order, while most non-GNU programs treat arguments starting with -
as operands if there is another operand before them. There are many variations on options (grouping, --
, etc.) which I won't go into here.
If your program takes two mandatory operands and a third optional operand, then the natural way is for the mandatory operands to be the first one and the second one, and the third operand be the optional one if present.
In a shell script, the arguments are "$1"
, "$2"
, "$3"
, etc. The number of arguments is $#
. If your script doesn't recognize any option, you can leave out option detection and treat all arguments as operands. See Michael Mrozek's answer for sample code. If you do want to recognize options, use the getopts
builtin (see your shell's documentation for examples).
Related videos on Youtube
Cold
Updated on September 18, 2022Comments
-
Cold almost 2 years
I'm creating a shell script and I need it to take two mandatory arguments and one optional. How do I check that? In most scripts I've seen, the optional arguments are passed before the mandatory ones, like:
cut -c2 test.txt
But for me this pattern would be complicated to check in the script, so my idea is to consider the third argument as optional.
-
Michael Mrozek over 9 yearsFor what it's worth, virtually all programs that take arguments that way won't care about the order (they frequently use
getopt
, which handles all that); you can docut test.txt -c2
and get the same result. If you don't care about the order, putting the optional arguments at the end seems trivial, so I'm not sure what your question is. Are you asking if there's an easy way to handle optional arguments at the beginning? -
Cold over 9 yearsThanks for editing @MichaelMrozek. I wonna know if there's an easy way to handle optional arguments? The order that the user give is not important.
-
terdon over 9 years@Cold it all depends on the code you are using. What language is this in, bash or another shell? How are you reading the arguments?
-
jw013 over 9 years@MichaelMrozek The POSIX standard
getopts
actually expects all option arguments to come before non-option arguments ("operands"). The script itself has to do extra work to support interleaving the two. I do not know aboutgetopt
since it is less standard and there are multiple (GNU and not GNU) versions out there.
-