A small Bash report tool may need only one named option and several file operands. Even this simple interface needs a clear boundary between options and filenames. Without it, a filename beginning with a dash may be mistaken for a flag, and unquoted argument expansion may turn one filename containing spaces into several operands.
Prerequisites: Bash on Linux. The parser was tested on GNU Bash 5.2.21. It only prints its interpretation of arguments; it does not open, delete or modify the named paths. No external commands or packages are required by the parser.
Define the command-line grammar
This script recognizes --label VALUE before operands. An explicit -- ends option parsing. The first ordinary operand also ends option parsing, so options cannot be interspersed with file operands. Repeating --label before operands assigns the most recent value. The label must be nonempty, and a following token is accepted as its value even if that token begins with a dash.
Bash documents positional parameters and shifting in its official reference manual. The positional-parameter reference also describes how these arguments are addressed.
Complete parser
Save as args.sh. Calling it with Bash avoids requiring an executable permission change.
#!/usr/bin/env bash
set -eu
label=report
while (( $# )); do
case "$1" in
--label)
if (( $# < 2 )) || [[ -z "$2" ]]; then
printf '%s\n' 'missing label value' >&2
exit 2
fi
label=$2
shift 2
;;
--) shift; break ;;
-*) printf 'unknown option: %s\n' "$1" >&2; exit 2 ;;
*) break ;;
esac
done
printf 'label=%s\n' "$label"
printf 'count=%s\n' "$#"
for path in "$@"; do
printf 'path=%s\n' "$path"
done
Run a normal case
bash args.sh --label 'daily report' -- '-draft.txt' 'two words.txt'
Expected output:
label=daily report
count=2
path=-draft.txt
path=two words.txt
The quotes preserve each argument before the script starts. Inside the script, quoted "$@" preserves the same argument boundaries while iterating. The explicit end-of-options token allows the leading-dash filename to reach the operand loop unchanged.
Check failure behavior
bash args.sh --label
bash args.sh --label ''
bash args.sh --unknown
bash args.sh
bash args.sh a.txt --label late
The first two invocations write missing label value to standard error and exit 2. The third writes unknown option: --unknown and exits 2. With no arguments, the script prints the default label and a count of zero. In the last invocation, the count is three because parsing stopped at a.txt; the later option-looking tokens are ordinary operands.
Edge cases and troubleshooting
The length check prevents a missing second positional parameter from being expanded under set -u. Short-circuit evaluation is part of that protection. Use a fixed format string with printf, keeping user-supplied text in separate arguments.
This output is for human inspection, not a machine-safe filename serialization. A filename containing a newline will span display lines. If another program must consume the operands, pass an argument array or use a deliberate NUL-delimited protocol. When adding a command that opens the paths, check that command's own end-of-options behavior too.
This is a Bash script: invoking it with a different shell can fail on arithmetic and conditional syntax. Explore more Linux tutorials.