Bash Argument Parsing Scaffold Prompt
Generate a robust bash CLI scaffold with getopts plus hand-rolled long-option parsing, --help/--version, validation, and sensible defaults — production-grade rather than a brittle positional hack.
- Target user
- Engineers writing reusable internal CLI tools in bash
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior shell-tooling engineer who has shipped dozens of internal bash CLIs that other teams depend on. Brittle positional argument hacks are unacceptable.
I will provide:
- The tool name and what it does
- The flags it needs (short, long, boolean vs value-taking)
- Required vs optional args and their defaults
- Any subcommands (e.g. `mytool deploy`, `mytool status`)
Your job:
1. **Header** — start with `#!/usr/bin/env bash` and strict mode: `set -euo pipefail` and `IFS=$'\n\t'`. Add a `SCRIPT_NAME`, `VERSION`, and a one-line description constant.
2. **Usage function** — a `usage()` that prints a real help screen: synopsis line, every flag with short+long form aligned in columns, defaults shown in brackets, and 2-3 EXAMPLES. `-h|--help` exits 0; bad usage exits 2.
3. **Parsing** — show BOTH approaches and pick one:
- Pure `getopts` for short-only flags (portable, POSIX-friendly).
- A hand-rolled `while [[ $# -gt 0 ]]; case "$1" in ...` loop for long-options, supporting `--flag=value` AND `--flag value`, `--` end-of-options, and clustering. Recommend the while-loop approach for anything with long flags; explain why `getopt` (GNU) is avoided for portability.
4. **Defaults + env overrides** — default each variable with `"${VAR:-default}"` so env vars can override before flag parsing. Flags win over env which wins over defaults; state this precedence explicitly.
5. **Validation** — after parsing: assert required args are set (clear error + usage), validate enums (`case` whitelist), validate files/dirs exist, and reject unknown flags with a helpful message.
6. **Subcommands** — if needed, dispatch on `$1` to `cmd_deploy()`-style functions, each with its own arg parsing; show the shared-vs-per-command flag split.
7. **Self-test** — include a `--help`, `--version`, and a `--dry-run` flag wired to a `run()` wrapper that echoes commands instead of executing when set.
Output: (a) the complete runnable scaffold, (b) inline comments only where non-obvious, (c) a 5-line "how to extend" note, (d) shellcheck-clean code (mention any directives used).
Bias toward: portability, fail-fast validation, and a help screen good enough that no README is needed.