Marcos
Marcos

Reputation: 895

Set specific option sets for arguments in bash

I've a script where I can pass different set of arguments for the work the script has to do. The options are specified below:

[Show Help] ./myscript.sh -h
[To Create] ./myscript.sh -c -f /input_loc/input_file.txt
[To Export] ./myscript.sh -e -d /destination_loc/exported_db_date.csv
[To Import] ./myscript.sh -i -s /source_loc/to_import_date.csv

And the script myscript.sh has getopts to parse the options and then push it to case - esac to apply checks and logics for each of the arguments passed to check their validity. For example, like below:

while getopts "cd:ef:his:" o; do
    case "${o}" in
        Put options and their check logics
    esac
done

My question is, what logic can I use to force arguments to be presented in particular sets only, for e.g.

Allowed Option set
./myscript.sh -h
./myscript.sh -c -f <file_name>
./myscript.sh -e -d <file_name>
./myscript.sh -i -s <file_name>

NOT Allowed Option set
./myscript.sh -h -c -f <file_name>
./myscript.sh -h -d <file_name>
./myscript.sh -e -s <file_name>
./myscript.sh -c -i -f <file_name>

Upvotes: 2

Views: 184

Answers (2)

Marcos
Marcos

Reputation: 895

I've used if...elif...else loop for this

#!/bin/bash
my_ary=("$@")
LEN=${#my_ary[@]}

if [[ ${my_ary[0]} =~ "-h" && $LEN -eq 1 ]] || \
   [[ ${my_ary[0]} =~ "-c" && ${my_ary[1]} =~ "-f" && $LEN -eq 3 ]] || \
   [[ ${my_ary[0]} =~ "-e" && ${my_ary[1]} =~ "-d" && $LEN -eq 3 ]] || \     
   [[ ${my_ary[0]} =~ "-i" && ${my_ary[1]} =~ "-s" && $LEN -eq 3 ]]; then
    echo "Proper set of arguments passed"

else
    echo "You are not passing arguments in proper sets, please look at Usage once again..."

fi

Is there a better way to do the same checks?

Upvotes: 1

Inian
Inian

Reputation: 85590

I think your specific usage of getopts() here is needed only to parse the valid option flags first and put them into an array and use the parsed flags later for ensuring only if the required order of flags are set.

The steps involved are two-fold. Firstly parse the valid flags to an array (multi) and secondly join the flags together without spaces and do a regex match on the provided flags, if you encounter ones that aren't allowed don't do your logic.

#!/usr/bin/env bash

while getopts "cd:ef:his:" opt; do
    case "$opt" in
      c|d|e|f|h|i|s) multi+=("$opt");;
      *) printf 'invalid flag provided' 1>&2 ; exit 1 ;;
    esac
done

joined=$(IFS=;echo "${multi[*]}")

if ! [[ $joined =~ ^(hcf|hd|es|cif)$ ]]; then
    printf 'valid flags provided\n'
    # Add your logic here
fi

Note, the answer does consider the option of swapping your flags order, i.e. if ./myscript.sh -h -c -f <file_name> isn't allowed, should ./myscript.sh -f <file_name> -h -c be allowed? Need to modify the answer based on that.

Upvotes: 1

Related Questions