1

Is possible to use getopts to force the user that run the script, to add the options?

I am not asking how to make an option to require a parameter (done with the : after the option), but how to actually tell the user that he need to add the -something when running the script.

Something like myscript.sh -f FILENAME; and if the user run the script as myscript.sh FILENAME he will get an error because he didn't add the -f option.

As now I check if $1 is empty or not, to print the usage message; and another statement to check if the -f option is in what the user passed; although if you have 10 options, you add 10 conditional statements? That feels a bit off and not efficient.

Once again, I am not asking how to handle getopts parameters, but the options themselves. I think the question is pretty clear to show that this has nothing to do with the answer mentioned as possible duplicate of this question.

Greenonline
  • 1,330
  • 8
  • 23
  • 31
  • Possible duplicate of [Bash Script with Parsing Argument in Linux](https://stackoverflow.com/questions/32826395/bash-script-with-parsing-argument-in-linux) – David C. Rankin Jan 31 '18 at 01:39
  • 1
    @DavidC.Rankin I don't think it is a duplicate; I am asking how to force a user to type the -[option], not how to force them to type the parameter for an option; they are 2 fundamentally different things. –  Feb 01 '18 at 02:50
  • I'm sorry, but that looked exactly what @glenn jackman's answer did. I see the distinction you are making, force a `-foo` option rather than the argument itself, but when you break it down, the only difference is whether your output complains about the missing parameter or the missing option. (meaning you are just flagging whether a specific option or parameter was received and issuing the appropriate warning) – David C. Rankin Feb 01 '18 at 04:34
  • Agree, the difference is to the extent of what you mentioned, but in my case, no argument AND no option is equally bad, and has to trigger a failure. I was assuming (wrongly), that getops will take care of everything but it was not correct. Thanks for your reply. –  Feb 02 '18 at 03:38

1 Answers1

0

Sounds like you want something like tar, which (usually) requires the user to specify an operation mode followed (usually) by the file name arguments. If that is the case, then no getopts alone will not help you. However, you can still use getopts to manage the arguments:

#!/bin/bash

help() {
    cat <<EOTXT
${1:-This program does something.}

USAGE:
  ${0##*/} <-abcde> <thing>

WHERE:
  -a Sets mode a
  ...
EOTXT
}

mode=0

OPTIND=1
while getopts abc opt; do
    case "${opt}" in
    a|b|c) mode=${opt};;
    ?) help "Unrecognized option"; exit 1;
    esac
done
shift "$((OPTIND-1))"

[[ 0 == ${mode} ]] && { help "Missing mode: use one of -a, -b, or -c"; exit 1; }
[[ 0 == $# ]] && { help "Missing thing argument"; exit 1; }

Here you use the typical while getopts construct to process your arguments. When it detects one of your required flags, you set the bookkeeping variable ($mode here) to the value. Then at the end, you check that you have both mode and an extra argument.

Thus all of these test cases fail:

my-program        # no mode or argument
my-program -a     # mode, but no argument
my-program foo    # argument, but no mode
my-program -d     # bad mode, no argument
my-program -d foo # bad mode with argument

Only this passes:

my-program -a foo
bishop
  • 37,830
  • 11
  • 104
  • 139
  • 1
    Awesome, thanks for the explanation! Indeed my objective is to avoid that a user will type something like `myscript [parameter]`, because for getops, this is "valid"; even if the user did not add the -[option] before the parameter. This goes way above and beyond, fixing also other cases; which is awesome. Thanks! –  Feb 01 '18 at 02:52