Bash — parse flags and an expected (non-optional) argument

argumentsbashgetoptsshell-script

$ bash file.sh expected_arg -f optional_arg

I've seen posts that address using $1 to grab the first argument

and posts that address using getopts for parsing flag arguments. I haven't seen a post that addresses both.

I'm currently accessing expected_arg via $1.

I can't process the -f flag at all. Even though I also have this in my test script:

#!/bin/bash

dirname=$1

[[ -z  $dirname  ]] && echo "Project name required as an argument." && return

# get flags
verbose='false'
aflag='false'
bflag='false'
files='false'
while getopts 'abf:v' flag; do
  case "${flag}" in
    a) aflag='true' ;;
    b) bflag='true' ;;
    f) files="${OPTARG}" ;;
    v) verbose='true' ;;
    *) error "Unexpected option ${flag}" ;;
  esac
done

echo "$files"

echo "$HOME/Desktop/$dirname"

exit

The terminal shows:

Jills-MBP:~ jillr$ bash test.sh blah -f file
false
/Users/jillr/Desktop/blah

Unless I switch the order of the arguments, as in:

bash file.sh -f optional_arg expected_arg

Which the terminal outputs:

Jills-MBP:~ jillr$ bash test.sh -f file blah
file
/Users/jillr/Desktop/-f

So naturally, -f is processed as $1, which isn't what I want. I need to grab the expected_arg

Constraints needed:

  • I need to allow for a varying number of flags (from none at all to several). Therefore, the position of expected_arg will vary
  • expected_arg is a must
  • I would rather avoid having to use another flag in order to parse expected_arg (as in, I want to avoid doing something like $ bash test.sh -f file -d blah)

How can I satisfy those constraints?

Best Answer

Nevermind. I found this post: Using getopts to parse options after a non-option argument

which basically says I can solve my issue simply by placing shift after dirname=$1

Which will allows for entering the arguments as

$ bash file.sh expected_arg -f optional_arg
Related Question