# Looking to shorten method of parsing arguments in BASH

I have here a working method of parsing input arguments however it seems redundant. I would like to shorten this code so it doesn't appear so repetitive.

tool.sh <file-to-use>
tool.sh <file-to-use> -o <output-file-name>

# If arguments are set and equals "-o" then set APP_NAME
if [[ -n $3 ]] && [[$2 = "-o" ]]; then
APP_NAME=$3 # If argument is set and equals anything besides "-o" throw error and show help menu elif [[ -n$2 ]] && [[ $2 != "-o" ]]; then echo "ERROR: Synatx error." bash$0 -h
exit

# If "-o" is set but they did not give a output name throw error and display help menu
elif [[ -z $3 ]] && [[$2 = "-o" ]]; then
echo "ERROR: Did not specify output file name."
bash $0 -h exit fi  ## 2 Answers Use the ${variable?error message} syntax to error on empty arguments. Use shift to remove parsed arguments from the positional parameters, so that the next unseen argument is always $1. If there are any arguments left at the end, there were too many. When a message isn't enough, you can use trap … EXIT to call a function on error. Remember to remove the trap after parsing and at the very start of your handler function. This version isn't any shorter than yours but it's more generic. You can add parameters or rearrange their order without altering the numbers in the existing logic. The error-handling is in one place instead of two. show_help() { trap - EXIT # omitting this can lead to an infinite loop exec$0 -h
exit
}

trap show_help EXIT
error_usage="Usage: $0 input-file [-o output-file]" input=${1?$error_usage} && shift [[$1 = -o ]] && output=${2?$error_usage} && shift 2
[[ -n $1 ]] && echo$error_usage && exit 0
trap - EXIT

echo "input=$input output=$output"


Rather than invoking ourselves to display help, I'd just put the help logic in the show_help function.

• Interesting thanks for the crash course! (Leveling up) – goose goose May 21 '19 at 23:13

Although tagged , this could easily be portable POSIX shell if we use [ rather than [[.

Always quote strings containing parameter expansions; even though you might think it unlikely that anyone would invoke the script with \$0 containing spaces (for example), if you don't code for it, then someone eventually will!

Error messages should always be directed to &2, and error exits should always be non-zero.

Consider using getopt for better argument handling (or at least loop over the arguments and use shift to consume them). Users don't like having to remember that -o filename has to come after the input file; they are used to commands that accept options in any reasonable order.

• yes this would be nice but it gets a bit confusing to me when you decide you dont want to use a flag for a input file. – goose goose May 22 '19 at 23:12
• Not a problem, if you say that any non-option argument is an input file. Do you need a demonstration of how that looks? – Toby Speight May 23 '19 at 7:29