Skip to content

Instantly share code, notes, and snippets.

@mca-gif
Last active June 7, 2024 20:30
Show Gist options
  • Save mca-gif/48b356fa4a0ed9b15f30521f81576999 to your computer and use it in GitHub Desktop.
Save mca-gif/48b356fa4a0ed9b15f30521f81576999 to your computer and use it in GitHub Desktop.
Template for Multi Command Bash Scripts
#!/usr/bin/env bash
# This is a template which provides a number of utilities I find useful when building a Bash script.
# It handles the case where one script may perform multiple commands, and that must be determined by arguments.
# Read comments marked with TODO for how to populate the script.
# This template also provides functionality to define and check for verbosity and debuginess, as well as constants which can be used to display color output.
VERBOSE=0
DEBUG=0
CMD=default
# TODO: Include any new optional flags below. See man getopt(1) for more information.
# You'll probably want to keep the help and verbose commands.
SHRT_OPTIONS="hv"
LONG_OPTIONS="help,verbose"
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cmd_default()
{
# TODO: Replace this with the things you actually want to do.
# Below is just an example to show you various features. Delete everything or nothing.
minimum_n_args 1 "$@"
local sample_argument=$1
log "You passed in ${sample_argument} as a value."
verbose "Verbose is enabled"
debug "Debugging is enabled"
error "And we terminate on an error"
}
main()
{
setup
local opts
opts=$(getopt -n "$(basename "$0")" -o ${SHRT_OPTIONS} --long ${LONG_OPTIONS} -- "$@")
if [[ $? -eq 1 ]]; then
usage
exit 1
fi
eval set -- "${opts}"
while true; do
case "$1" in
-h|--help)
usage; exit 0 ;;
-v|--verbose)
if [[ ${VERBOSE} -eq 1 ]]; then
DEBUG=1
fi
VERBOSE=1
shift ;;
# TODO: Add handlers for the above flags here. It is advised to keep the code short merely setting a variable for use later.
--) shift; break ;;
*) usage; exit 1;
esac
done
### TODO: If this script is just a single command which accepts multiple arguments, uncomment the following line and delete the rest of the function.
# cmd_default "$@"
### The below section is only necessary if you want to implement multiple sub-commands within this script.
if [[ $# -ge 1 ]]; then
CMD=$1
shift;
fi
case ${CMD} in
# TODO: Place handlers for your actual commands here. It is advised to make a call out to another function, to keep this area clean.
# The internal convention is to prefix the function with "cmd_" and name it the name of the command.
# At this point $@ should equal any unprocessed arguments supplied at the command-line, so passing the entire array is "safe"
"default")
cmd_default "$@"
;;
*)
warn "Invalid command provided."
usage
exit 1
esac
}
usage()
{
### BASIC USAGE ###
log "Usage: $(basename "$0") [--help] [command]"
log ""
### OPTION SECTION ###
log "Options include:"
log " -h --help\t\t Display this help."
log " -v --verbose\t\t Enable verbose output. Specifying this more than once will enable debug output."
# TODO: Add descriptions of your options here.
# Formating convention is: <SPACE><SPACE><SPACE><DASH><LETTER><SPACE><DASH><DASH><NAME><TAB><TAB><SPACE><DESCRIPTION>
# If argument names are shorter or longer, tabs should be adjusted to keep alignment. If too long, a new line should be created.
# log " -e --example\t\tThis is an example option."
log ""
### COMMAND SECTION ###
# If you don't need any additional commands, and are just using the default, delete the section below.
log "Commands:"
# TODO: Add descriptions of your commands here.
# Formatting is: <SPACE><SPACE><SPACE><NAME><TAB><TAB><SPACE><DESCRIPTION>
log " default\t\t Description of the command here. By default just display some info"
log ""
}
# Configure colors
setup()
{
if test -t 1; then
# see if it supports colors...
local ncolors
ncolors=$(tput colors) || true
if test -n "$ncolors" && test "$ncolors" -ge 8; then
TRESET="$(tput sgr0)"
TSMUL="$(tput smul)"
TRMUL="$(tput rmul)"
TBOLD="$(tput bold)"
TUNDERLINE="$(tput smul)"
TSTANDOUT="$(tput smso)"
TBLACK="$(tput setaf 0)"
TRED="$(tput setaf 1)"
TGREEN="$(tput setaf 2)"
TYELLOW="$(tput setaf 3)"
TBLUE="$(tput setaf 4)"
TMAGENTA="$(tput setaf 5)"
TCYAN="$(tput setaf 6)"
TWHITE="$(tput setaf 7)"
fi
export TRESET
export TSMUL
export TRMUL
export TBOLD
export TUNDERLINE
export TSTANDOUT
export TBLACK
export TRED
export TGREEN
export TYELLOW
export TBLUE
export TMAGENTA
export TCYAN
export TWHITE
fi
}
log()
{
echo -e "$@" >&1
}
error()
{
echo -e "$@" >&2
exit 1
}
warn()
{
echo -e "$@" >&2
}
verbose()
{
[[ ${VERBOSE} -eq 0 ]] || echo -e "$@" >&1
}
# Determine if verbose mode is enabled.
# Example usage: is_verbose && echo "One liner example"
# Example usage: if is_verbose; then echo "Multiple line example"; done
is_verbose()
{
[[ ${VERBOSE} -eq 0 ]] && return 1 || return 0
}
debug()
{
[[ ${DEBUG} -eq 0 ]] || echo -e "$@" >&1
}
# Determine if debug mode is enabled.
# Example usage: is_debug && echo "One liner example"
# Example usage: if is_debug; then echo "Multiple line example"; done
is_debug()
{
[[ ${DEBUG} -eq 0 ]] && return 1 || return 0
}
# Throws an error if EXACTLY n-number of arguments were supplied.
# For use inside of functions to verify enough arguments were supplied.
# Must supply the quantity of arguments and the arguments provided to the function in a specific way.
# Example usage: require_n_args 2 "$@"
require_n_args() {
(( reqcnt = $1 + 1 ))
if [[ $# -eq $reqcnt ]]; then
return 0;
else
error "The incorrect number of arguments were specified."
fi
}
# Throws an error if AT LEAST n-number of arguments were supplied.
# For use inside of functions to verify enough arguments were supplied.
# Must supply the quantity of arguments and the arguments provided to the function in a specific way.
# Example usage: minimum_n_args 2 "$@"
minimum_n_args() {
(( reqcnt = $1 + 1 ))
if [[ $# -ge $reqcnt ]]; then
return 0;
else
error "The incorrect number of arguments were specified."
fi
}
main "$@"
@sganous
Copy link

sganous commented Feb 24, 2021

Oh that's so useful. I'm saving this one. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment