$ 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:



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

# get flags
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}" ;;

echo "$files"

echo "$HOME/Desktop/$dirname"


The terminal shows:

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

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

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?

1 Answer 1


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
  • +1, yep shift is what you need here....but it's generally better not to assume a fixed position for an argument, especially if you might have more than one non-option argument. in other words, it's better to process the options first, then you know that whatever is remaining are non-options. One of the reasons for using getopts (or getopt) is that you don't have to know the order of args, or even the number of args.
    – cas
    Aug 8, 2017 at 2:15
  • @cas feel free to post an implementation ;) :D
    – user243760
    Aug 8, 2017 at 14:21
  • the implementation is your code above except you don't have dirname=$1 or the test for -z $dirname before the getopts, you have them after the getopts processing, when all that's left is non-option args. and you double-quote both $dirname and $1 too, because that's what you should do when referencing a variable (or positional parameter), especially when they come from unknown/uncontrolled sources like command-line arguments.
    – cas
    Aug 8, 2017 at 14:30

You must log in to answer this question.