Skip to content
Advertisement

How to validate the number of arguments (mandatory and optional) in a shell script?

I am having trouble validating my script arguments. I am trying to achieve 5 mandatory arguments and 2 optional arguments to my script. Here is what I have tried so far.

JavaScript

The problem is validating the total number of arguments to this script as I can have a total of 5 or 7 arguments. Providing -a additional -c character is treated as 9 arguments.

JavaScript

I am open to designs with no - as long as I am able to have both mandatory and optional parameters.

How to get this properly validated?

Advertisement

Answer

First: the shell doesn’t know anything about optional vs. mandatory arguments, doesn’t treat arguments that start with “-” specially, anything like that. It just has a list of “words”, and it’s up to your script to figure out what they mean. The getopts command can help with parsing the arguments, but it handles a fairly limited syntax:

  • Options start with a single dash, and are a single letter (maybe with an argument after that). For options that don’t take arguments, you can stack multiple options on a single dash (e.g. ls -la).
  • After all the options, there can be a number of positional parameters (the meaning of these is defined — as the name implies — by their position in the list, e.g. first, second, etc).

There are a number of syntax extensions (mostly GNU conventions) that getopts does not support:

  • Putting options after positional parameters (e.g. ls filename -l). Options must always come first.
  • Long options (multi-letter and/or double-dash, e.g. ls --all).
  • Using -- to separate the options from the positional parameters.

So if you want to use getopts-style optional arguments, you need to put them first in the argument list. And when parsing them, you need to parse and remove* them from the argument list (with shift) before you check the number of positional parameters, and use $1 etc to access the positional parameters. Your current script is running into trouble because it’s trying to handle the positional parameters first, and that won’t work with getopts (at least without some heavy-duty kluging).

If you need a more general argument syntax, you might be able to use getopt (note the lack of “s” in the name). Some versions of getopt support the GNU conventions, some don’t. Some have other problems. IMO this is a can of worms that’s best left unopened.

Another possibility is to abandon the - option syntax, and give the script 7 positional parameters where the last two can be omitted. The problem with this is that you can’t omit the sixth but pass the seventh (unless you’re willing to consider the sixth being blank as equivalent to omitting it). The code for this would look something like this:

JavaScript

…and then run the script with e.g.

JavaScript

Or, if you really want the more extended syntax and don’t want to risk the vagaries of the getopt command, you can spend a lot of time and effort writing your own parsing system. IMO this is way more work than it’s worth.

Advertisement