Instantly share code, notes, and snippets.

Embed
What would you like to do?
Quick and Dirty Bash Script Template
#!/bin/bash
##----------------
export script_name=$(basename -a "$0")
export script_short_desc="
A script for doing things."
export script_mod_date='0000.00.00-00:00'
export script_version='0.0.1'
export script_requirements='none'
##----------------
shopt -s extglob ## Needed for arg parsing
## Internal config
export script_subcommands_args=()
export script_min_args=1
## Script Config
export working_dir=${working_dir:-"$PWD"}
# ----------------------------------------------------------------------------------------------
## Script
do_work() {
echo "doing work in ${working_dir}"
}
## Args
parseArgs() {
local args=("$@")
while (( "${#args}" )); do
case "$1" in
-@([a-z|A-Z]*))
# Switches
parseSwitches "$1"
;;
--*)
# Options
parseOptions "$1"
;;
*)
# Subcommands args stored as an array for later. For more
# complicated scripts, sometimes we need to act on the
# switches/options or source configuration first before we run
# the subcommands.
script_subcommands_args=("$@")
break
;;
esac
shift
args=("$@")
done
shopt -u extglob
# Check for minimum number of arguments/subcommands beyond switches and options here.
if [[ ${#script_subcommands_args[@]} < $script_min_args ]]; then
echo "Syntax error: a minimum of $script_min_args arguments required."
echo ""
usage_short
exit 1
fi
}
parseSwitches() {
local switches="$1"
switches="${switches:1}"
while (( "${#switches}" )); do
# Handle actions for individual switches here
case "${switches:0:1}" in
h)
usage_short
exit 0
;;
v)
version
exit 0
;;
*)
echo "Error: "${switches:0:1}" not a valid switch"
echo ""
usage_short
exit 1
;;
esac
switches="${switches:1}"
done
}
parseOptions() {
local option=( $( IFS='='; echo ${1} ) )
local option_keyword=${option[0]:2}
# Get value of option if there is any
local option_value=${option[@]:1}
# Handle actions for individual options here
case "${option_keyword}" in
help)
usage
exit 0
;;
version)
version
exit 0
;;
*)
echo "Error: "${option_keyword}" not a valid option"
echo ""
usage_short
exit 1
;;
esac
}
parseSubcommands() {
local args=("$@")
while (( "${#args}" )); do
case "$1" in
work)
echo "Args passed to work command: ${args[@]:1}"
break
;;
*)
echo "Error: "$1" not a valid subcommand"
usage
exit 1
;;
esac
shift
args=("$@")
done
}
## Dialogs
usage_cli=$(cat <<EOF
Usage: ${script_name} <args>
${script_short_desc}
EOF
)
usage_args=$(cat <<EOF
Switches/Options:
-v|--version Version
-h|--help Short|Full help
Subcommands
work Werk it
EOF
)
usage_short() {
cat <<EOF
${usage_cli}
${usage_args}
Run '${script_name} --help' for the full help documentation.
EOF
}
usage() {
cat <<EOF
${usage_cli}
Switches can be combined, or used individually, in any order. Options must
follow the format --option="something here" and not have spaces in between
the option keyword and it's value.
By default:
- Any arguments that aren't switches or options are treated as erroneous, but
they could potentially be main arguments subcommands.
- The script processes all switches and all options, but stops only if
"exit" is declared in any of the 'case' statements. This is the current
behavior but can be easily changed.
${usage_args}
Requirements:
${script_requirements}
Version:
${script_name} version: ${script_version}
Last modifed on: ${script_mod_date}
EOF
}
version() {
echo "${script_name} version: ${script_version}"
echo "Last modifed on: ${script_mod_date}"
}
## Sequence
main() {
set -eo pipefail
parseArgs "$@"
parseSubcommands "${script_subcommands_args[@]}"
# Default behavior
do_work
}
## Runtime
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment