To parse CLI args (i.e. -p/--path /some/path or -n/--name myname), you can write a while loop that iterates over your args. You use $# to get the number of CLI args, and if there are any, a case statement to do things with the inputs.
#!/bin/bash## Set defaultsNAME="world"## Parse argswhile[[$#-gt0]];do# ensure there are or more positional args to parse## Case statement to arse that --arg and a value if one was passedcase"$1"in-n|--name)# catch -n or --name## Ensure a name value was passed with the argif[[-z$2]];then## User passed -n/--name without a name valueecho"[ERROR] --name provided but no name given."exit1fi## Set value of NAME var to provided nameNAME="$2"## Shift 2, because there are 2 positional args (-n/--name and the name value given)shift2;;*)# catch any misspelled or invalid argsecho"[ERROR] Invalid flag: $1"echo"You could print the CLI usage here as a hint to the user."exit1;;esacdoneecho"Hello, $NAME"
Pass a flag multiple times
You can store arg inputs in an array, so that you can pass the arg multiple times.
#!/bin/bash## Set defaultsdeclare-aADD=()## Parse argswhile[[$#-gt0]];docase"$1"in-a|--add)# accept -a/--add multiple timesif[[-n"$2"&&"$2"!=--*]]# ensure a value was passed, and was not another --argADD+=("$2")shift2elseecho"[ERROR] --add provided but no integer given."exit1fi;;*)echo"[ERROR] Invalid argument: $1"exit1;;esacdone## Sum --add valuessum=0forvalin"${ADD[@]}";do((sum+=val))doneecho"Sum: $sum"
Switch/boolean args
To uses an arg as a switch, you can detect its presence and set a static action, like settings a DRY_RUN variable.
#!/bin/bashDRY_RUN=""while[[$#-gt0]];docase"$1"in--dry-run)## Set the $DRY_RUN value to 'true'DRY_RUN="true"## "shift" to the next argshift;;esacdoneif[["$DRY_RUN"==""]]||[["$DRY_RUN"=="false"]];thenecho"Dry run is not enabled."elseecho"Dry run is enabled."fi
#!/bin/bash## Set default values before parsing# When --dry-run is passed, this will be set to 'true'DRY_RUN=""# User can pass a -n/--name to override thisNAME="world"## An array the user can append to with multiple -l/--ls-dirdeclare-aLS_DIRS=()## Function to print CLI usage on error or -h/--helpfunctionprint_help(){cat<<EOFUsage: $0 [options]Options: -n, --name NAME Specify a name (default: world) -l, --ls-dir PATH Add path to list (can be repeated; default: current dir) --dry-run Run without making changes -h, --help Show this help messageEOF}## Parse CLI argswhile[[$#-gt0]];docase"$1"in-n|--name)## Evaluate the 2nd positional arg, which sould be a name stringif[[-z$2]];then## User passed -n/--name with no name valueecho"[ERROR] --name provided but no name string given."exit1fiNAME="$2"## Shift 2, because of the 2 position args (-n/--name and the name provided)shift2;;-l|--ls-dir)## This arg can be passed multiple times. Loop over all iterations,# evaluate them, and append them to the arrayif[[-n"$2"&&"$2"!=--*]];then## A path was found, append it to LS_DIRSLS_DIRS+=("$2")shift2elseecho"[ERROR] --ls-dir provided but no path given."print_help
exit1fi;;--dry-run)## Set the $DRY_RUN value to 'true'DRY_RUN="true"## "shift" to the next argshift;;## Catch -h/--help and exit early-h|--help)print_help
exit0;;## Catch any misspellings or invalid args*)echo"[ERROR] Invalid argument: $1"## Print the script help menuprint_help
exit1;;esacdonefunctionsay_hi(){localname
name="$1"echo"Hello, $name!"}functionloop_dirs(){localdirs=("$@")if[[${#dirs[@]}-eq0]];thenecho"[WARNING] No --ls-dir paths given."return0fifordin"${dirs[@]}";do## Ensure path existsif[[!-d"$d"]];thenecho"[WARNING] Could not find path: $d"continuefiecho""echo"Listing files in path: $d"echo""## List contentsls-la"$d"done}say_hi"$NAME"if[["$DRY_RUN"==true]];thenecho"[DRY RUN] Would list directories: ${LS_DIRS[*]}"elseloop_dirs"${LS_DIRS[@]}"fi