I'm using this to get keyword arguments for my shell script

while [[ $# -gt 0 ]]; do
  case $key in
      shift # past argument
      shift # past value
      shift # past argument
      shift # past value
      shift # past argument
      shift # past value
      *) echo "Improper usage"; exit 1;;

Now the job variable usually is multi-word. I can give the whole value for that argument inside a quote and it works perfectly. But is it possible to provide the value without any quote but still store inside that single variable. For example, this works

./myscript -j "my long string"

and it stores "my long string" to the variable job. But I want this to work too similarly,

./myscript -j my long string
  • 3
    My question is, why? It's possible tho, but why?
    – annahri
    Commented Dec 15, 2021 at 9:52
  • how about concatenating $2 $3 $4 $...
    – derwana
    Commented Dec 15, 2021 at 10:05
  • 4
    Don't. That would be contrary to all the usual customs for command line arg processing, and might make some users really confused. Also you'd have issues if you ever need to take other args after the job string, ./myscript -j "foo bar" file.txt is clear, but ./myscript -j foo bar file.txt is ambiguous. Or with other options, where does the string end in: ./myscript -j foo bar -u user? You could decide the next arg starting with a dash ends the string and is itself taken as an option, but then you'd be limiting the allowed set of values in the job string.
    – ilkkachu
    Commented Dec 15, 2021 at 10:26

1 Answer 1


You could pick the remaining parameters with "$*", but I really wouldn't recommend it. The standard expectation is that option flags should take no more than a single parameter value.

usage="Usage: $progname -u <userid> -n <jobname> -j <job>"

while getopts ':u:n:j:' OPT
    case "$OPT" in
        u)      userid="$OPTARG" ;;
        n)      jobname="$OPTARG" ;;
        j)      job="$OPTARG" ;;
        ?)      echo "$usage" >&2; exit 1 ;;
shift $(($OPTIND - 1))

# Append any remaining arguments to the job
[[ $# -gt 0 ]] && job="${job:+$job }$*"

printf "userid=%s, jobname=%s, job=%s.\n" "$userid" "$jobname" "$job"
exit 0

To stay within standard expectations, do not include the line that appends remaining arguments to the job.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .