This question already has an answer here:

Most shell scripts I use have syntax like

./shellscript.sh -first_argument_flag <first_argument_value> -second_argument_flag <second_argument_value>

but all of the online resources for shell scripters only discuss passing positional arguments like

./shellscript.sh <first_argument_value> <second_argument_value> 

which are subsequently used in the script as "$1" , "$2", etc.

I would like to use the first, more user-friendly syntax rather than the positional argument syntax. As an example, suppose I want to echo a filename with flag -f and a directory with flag -d. Call this script echofd.sh. I want

./echofd.sh -f myfile.txt -d /my/directory/ 

to produce the output

Your File is: myfile.txt

Your Directory is: /my/directory/

and regardless of which order -f and -d are positioned in calling the script.

marked as duplicate by Thomas Dickey, Satō Katsura, countermode, HalosGhost, GAD3R Nov 4 '16 at 18:40

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    Most people use getopts (or getopt) to do this, and this topic has been discussed several times. – Thomas Dickey Nov 4 '16 at 17:56

There's the getopts standard (builtin) utility in POSIX shells for parsing command line arguments.

You can use this template:

#! /bin/sh -

usage() {
  cat << EOF >&2
Usage: $PROGNAME [-v] [-d <dir>] [-f <file>]

-f <file>: ...
 -d <dir>: ...
       -v: ...
  exit 1

dir=default_dir file=default_file verbose_level=0
while getopts d:f:v o; do
  case $o in
    (f) file=$OPTARG;;
    (d) dir=$OPTARG;;
    (v) verbose_level=$((verbose_level + 1));;
    (*) usage
shift "$((OPTIND - 1))"

echo Remaining arguments: "$@"

That parses the arguments in the standard way, like other standard commands would. for instance, you can call it as:

myscript -vvv -f file -d dir other arg
myscript -ffile -ddir -- other arg

See the POSIX specification or your shell manual for details.


parse_args() {
    case "$1" in
            echo "Unknown or badly placed parameter '$1'." 1>&2
            exit 1

while [[ "$#" -ge 2 ]]; do
    parse_args "$1" "$2"
    shift; shift

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