Quick references to common and useful bash programming snippets and boilerplate.
Last active
July 3, 2024 17:14
-
-
Save jaytaylor/8f7e93f7c235367e20f0cae116bcf4c0 to your computer and use it in GitHub Desktop.
jaytaylor's Bash shell skeleton programming snippets quick reference
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
main() { | |
printf '%s\n' "INFO: $(basename "$0"):${FUNCNAME[0]}:${LINENO}: Hello world" 1>&2 | |
} | |
export -f main | |
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "${BASH_SOURCE[0]}" = '--' ]; then | |
set -o errexit | |
set -o pipefail | |
set -o nounset | |
if [ "${1:-}" = '-v' ]; then | |
printf '%s\n' "INFO: $(basename "$0")::${LINENO}: Verbose output enabled" 1>&2 | |
shift | |
set -o xtrace | |
fi | |
main "$@" | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
_ts() { date -u +'%Y-%m-%dT%H:%M:%S%z'; } | |
log_debug() { printf '%s\n' "$(_ts) DEBUG: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2; } | |
log_info() { printf '%s\n' "$(_ts) INFO: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2; } | |
log_warn() { printf '%s\n' "$(_ts) WARN: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2; } | |
log_error() { printf '%s\n' "$(_ts) ERROR: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2; } | |
die() { log_error "$*"; exit 1; } | |
export -f _ts | |
export -f log_debug | |
export -f log_info | |
export -f log_warn | |
export -f log_error | |
export -f die | |
# n.b. alternate one-liner hack form: | |
# eval "$(for x in info warn error; do echo -e "log_${x}() { echo \"\$(_ts) $(echo ${x} | tr [:lower:] [:upper:]): \$*\"; };"; done)" | |
usage() { printf '%s\n' "usage: $0 [-v?] ..."; } | |
main() { | |
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then | |
usage | |
return 0 | |
fi | |
} | |
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "${BASH_SOURCE[0]}" = '--' ]; then | |
set -o errexit | |
set -o pipefail | |
set -o nounset | |
if [ "${1:-}" = '-v' ]; then | |
log_debug 'verbose mode enabled' | |
shift | |
set -o xtrace | |
fi | |
main "$@" | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
_ts() { | |
date -u +'%Y-%m-%dT%H:%M:%S%z' | |
} | |
export -f _ts | |
log_debug() { | |
printf '%s\n' "$(_ts) DEBUG: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2 | |
} | |
export -f log_debug | |
log_info() { | |
printf '%s\n' "$(_ts) INFO: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2 | |
} | |
export -f log_info | |
log_warn() { | |
printf '%s\n' "$(_ts) WARN: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2 | |
} | |
export -f log_warn | |
log_error() { | |
printf '%s\n' "$(_ts) ERROR: $(basename "$0"):$(caller 0 | awk '{ print $2 ":" $1 }') $*" 1>&2 | |
} | |
export -f log_error | |
die() { | |
log_error "$*" | |
exit 1 | |
} | |
export -f die | |
#export -f _ts | |
#export -f log_debug | |
#export -f log_info | |
#export -f log_warn | |
#export -f log_error | |
#export -f die | |
# n.b. alternate one-liner hack form: | |
# eval "$(for x in info warn error; do echo -e "log_${x}() { echo \"\$(_ts) $(echo ${x} | tr [:lower:] [:upper:]): \$*\"; };"; done)" | |
usage() { | |
echo "usage: $0 [-v?] ..." | |
} | |
main() { | |
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then | |
usage | |
return 0 | |
fi | |
} | |
# TODO: Revisit this, behavior seems different from what I observed on | |
# Kubernetes last week. Currently not working properly. | |
## n.b. Checking for '--' will activate main in cases where the script body has | |
## been passed in as a string argument. | |
## | |
## Example: | |
## bash -c 'echo "args=\"$@\" BASH_SOURCE[0]=\""${BASH_SOURCE}"\""' -- -v | |
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "${BASH_SOURCE[0]}" = '--' ]; then | |
set -o errexit | |
set -o pipefail | |
set -o nounset | |
if [ "${1:-}" = '-v' ]; then | |
printf '%s\n' 'INFO: Verbose output enabled' 1>&2 | |
shift | |
set -o xtrace | |
fi | |
main "$@" | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
die() { | |
printf '%s\n' "ERROR: $*" 1>&2 | |
exit 1 | |
} | |
export -f die | |
usage() { | |
printf '%s\n' "usage: $0 [-v?] ..." | |
} | |
main() { | |
if [[ "${1:-}" =~ ^(-h|--help)$ ]]; then | |
usage | |
return 0 | |
fi | |
} | |
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "${BASH_SOURCE[0]}" = '--' ]; then | |
set -o errexit | |
set -o pipefail | |
set -o nounset | |
if [ "${1:-}" = '-v' ]; then | |
printf '%s\n' 'INFO: Verbose output enabled' 1>&2 | |
shift | |
set -o xtrace | |
fi | |
main "$@" | |
fi |
https://stackoverflow.com/a/9612232/293064
find '.' -print0 | while IFS= read -d '' -r line; do
echo "line=${line}"
done
Bash equivalent to if __name__ == '__main__':
in Python.
n.b. The '--'
part needs to be revisited. Yesterday (Sunday 2020-02-09) I was unable to reproduce the behavior previously observed in Kubernetes a few weeks ago.
if [ "${BASH_SOURCE[0]}" = "${0}" ] || [ "${BASH_SOURCE[0]}" = '--' ]; then
main "$@"
fi
This can also be thought of as a reverse of the shift
command.
Works for both scripts and functions.
Credit: Source
last="${@:$#}"
set -- "${@:1:$(($#-1))}"
# trappend is like trap, with the addition that if there is an existing trap
# already set, it will append the new command(s) without clobbering the
# pre-existing trap orders.
#
# n.b. Won't work for RETURN (hopefully this is somewhat obvious ;).
#
# usage: trappend cmds.. SIGNAL
trappend() {
local sig
local existing
# n.b. Reverse-shift operation.
sig="${*:$#}"
set -- "${@:1:$(($#-1))}"
if [ "${sig}" = 'RETURN' ]; then
echo 'ERROR: trappend: SIGNAL value cannot be "RETURN"' 1>&2
return 1
fi
if [ -n "$(trap -p "${sig}")" ]; then
existing="$(trap -p "${sig}" | sed "s/^trap -- '\(.*\)' ${sig}\$/\1/");"
fi
# shellcheck disable=SC2064
trap "${existing:-}$*" "${sig}"
}
trappend 'echo hello 3' EXIT
trappend 'echo hello 4' EXIT
echo hello 0
echo hello 1
Output:
hello 0
hello 1
hello 3
hello 4
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment