0

I have a shell script which accepts 4 input options (x:m:b:v). But i want to restrict my input option like.

Condition 1

1. Accept option x or x and b
   eg: sh script -x <arg> (or)             ;will execute function a defined in script
       sh script -x <arg> -b               ;will execute the functions a and b

Condition 2

2. Accept option m or m and b
   eg: sh script -m <arg> (or)     ;execute function c
       sh script -m <arg1> -b   ;should execute function for c and b

Condition 3

3. Option both x and m should not be passed together.
   This will print usage(how to use the input options) function.

Condition 4

4. Option v. This should not be passed with any other option.
   eg: sh script -v <arg>  ; executs the function for v

I know this can be achievable with if and else conditions, but i am unable to get the logic for the conditions.

Also if none of the input arguments are passed (or) if all the input arguments are passed it should execute usage function.

  • "Use the Source, Luke!" The beauty of the open source world is that you can improve your skills by studying other people's code. I'd suggest you find a well-known utility that has similar kinds of option overlap/exclusion rules, and look at their code to see how they did it. – Jim L. May 29 '19 at 19:13
2

As an example to illustrate my comment above, here is an excerpt from FreeBSD's /usr/src/bin/cp/cp.c:

while ((ch = getopt(argc, argv, "HLPRafilnprsvx")) != -1)
        switch (ch) {
        case 'H':
                Hflag = 1;
                Lflag = 0;
                break;
        case 'L':
                Lflag = 1;
                Hflag = 0;
                break;
        ...
        case 'l':
                lflag = 1;
                break;
        ...
        case 's':
                sflag = 1;
                break;
        case 'v':
                vflag = 1;
                break;
        case 'x':
                fts_options |= FTS_XDEV;
                break;
        default:
                usage();
                break;
        }

Notice that the above sets a lot of boolean variables like Hflag, Lflag, lflag, sflag, etc. This not only allows the code to test boolean relationships between flags, but it also allows the presence of one flag to activate another, or to override another. Also notice that the default clause of the switch statement forces a usage() call when the user specifies an undefined option flag.

As for flag exclusions, such as disallowing mflag && xflag, a similar case appears in cp.c:

if (lflag && sflag)
        errx(1, "the -l and -s options may not be specified together");

Here is a possible translation of that code from C into bash with additional adaptation to your example:

flagb=
flagm=
flagv=
flagx=

while getopts "bm:vx:" ch
do

        case "$ch" in
        [bv])
                eval flag$ch=1
                printf 'flag%s set\n' "$ch"
                ;;
        [mx])
                eval flag$ch=1
                eval arg$ch=\"$OPTARG\"
                printf 'flag%s set\n' "$ch"
                printf 'arg%s is "%s"\n' "$ch" "$OPTARG"
                ;;
        -)
                break
                ;;
        esac

done

[[ $OPTIND > 1 ]] && shift $(($OPTIND-1))

if [[ "$flagv" ]]
then
        if [[ -n "$flagb$flagm$flagx" ]]
        then
                printf 'error: -v cannot be used with any other flags\n' >&2
                exit 2
        fi
fi

if [[ "$flagm$flagx" = "11" ]]
then
        printf 'error: -m and -x cannot be used together\n' >&2
        exit 2
fi

if [[ "$flagb" ]] && ! [[ "$flagm$flagx" ]]
then
        printf 'error: -b requires either -m or -x\n' >&2
        exit 2
fi

[[ "$flagb" ]] && printf 'b flag is set\n'
[[ "$flagm" ]] && printf 'm flag is set, arg is "%s"\n' "$argm"
[[ "$flagv" ]] && printf 'v flag is set\n'
[[ "$flagx" ]] && printf 'x flag is set, arg is "%s"\n' "$argx"

[[ "$@" ]] && {
        printf 'remaining arguments:'
        printf ' "%s"' "$@"
        printf '\n'
}
|improve this answer|||||
  • Thanks will check – upkar May 29 '19 at 19:45
  • Modifying this to match the question wouldn't seem too hard, and would likely be worth an upvote :) – ilkkachu Jul 25 '19 at 11:05
  • @ilkkachu Good idea! – Jim L. Jul 25 '19 at 18:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.