3 ms·
Ask HN: How do you implement option flags in your shell scripts?
I've been writing some Bash scripts for my team and I want to add option flags for a small variety of things. I'm very familiar with BASH and the shell, but have never written scripts that would be consumed by anyone other than me.
What common patterns, conventions, or idioms do you use to implement options in your shell scripts?
Examples of options I want to implement:
- [-h | --help] Prints a help message.
- [-t | --target] Points to a directory containing our automated tests.
- [-e | --env] Takes a string URI for the automated tests to run against (e.g. http://localhost:1234 or https://tst.mycloudenv.hn).
- [-q | --quiet] Suppresses output.
Capabilities:
- Long or short options.
- Options can appear in any order.
- Options are properly interpreted anywhere in the command, besides the last position.
- Short options can be concatenated.
Essentially, I want these to be as professional and POSIX compliant as possible [0].
[0] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html
- smoldesu 3y agoRed Hat has a pretty excellent article on this: https://www.redhat.com/sysadmin/arguments-options-bash-scripts https://www.redhat.com/sysadmin/arguments-options-bash-scrip...
- DiggyJohnson 3y agoThanks, this is exactly the sort of thing I was looking for.
- LinuxBender 3y agoI don't have one specific method I stick with but here [1] are some popular examples. [1] - https://stackoverflow.com/questions/7069682/how-to-get-arguments-with-flags-in-bash https://stackoverflow.com/questions/7069682/how-to-get-argum...
- da-x 3y agoRecursive decent parsing! For example, here's a template for a script, with a `main` function, parsing for an `--interactive` flag, and handling of positional arguments. If you want an option to take an argument, you can simple extend the `case` with a new option, with shift and take `$1`. #!/bin/bash set -eu set -o pipefail set +o posix main() { local interactive=0 local positional=() while [[ $# != 0 ]] ; do if [[ "$1" =~ ^--(.*)$ ]] ; then shift local param param="${BASH_REMATCH[1]}" case ${param} in interactive) interactive=1 ;; *) "invalid parameter ${param}"; return 1 ;; esac else positional+=("$1") shift fi done set -- "${positional[@]}" if [[ "${interactive}" == "1" ]] ; then echo "I am interactive" else echo "I am not interactive" fi echo "Rest of my arguments: "$@ } main "$@"