Skip to content

Instantly share code, notes, and snippets.

@zhum
Last active May 1, 2023 10:41
Show Gist options
  • Save zhum/47c9bcdbb7965fd0d1e6a49212286487 to your computer and use it in GitHub Desktop.
Save zhum/47c9bcdbb7965fd0d1e6a49212286487 to your computer and use it in GitHub Desktop.
Bash script template with usefull things
#!/usr/bin/env bash
#
# YOUR DESCRIPTION HERE
#
#
# check it with https://www.shellcheck.net/
# set -e = FAIL if any command fails
# set -o pipefail = FAIL if any command in the pipe fails
# set -u = FAIL if any variable is used, but not initialized
if test "$BASH" = "" || "$BASH" -uc "a=();true \"\${a[@]}\"" 2>/dev/null; then
# Bash 4.4, Zsh
set -euo pipefail
else
# Bash 4.3 and older chokes on empty arrays with set -u.
set -eo pipefail
fi
# expand * ALWAYS, even if in empty dirs, expand ** recursively
shopt -s nullglob globstar
# require(){ hash "$@" || exit 127; }
function require() {
for function_to_hash in "${@}"; do
local function_exists="$(command -v "${function_to_hash:-}" 2>/dev/null || :)"
if [[ -z "${function_exists:-}" ]]; then
echo "missing command ${function_to_hash:-}"; exit 1
fi
hash -p "${function_exists}" "${function_to_hash}"
done
}
require 'find'
require 'grep' # etc...
# tune it for your script!
cleanup() {
true
#rm -f "$tmpfile"
#...
}
trap cleanup EXIT
#####################################################
# hints
# redirect stderr to another process (stdout is dropped)
# (my-task > /dev/null) 2> >(sed -ne '/^EMERG: /p')
# use defaults
# var="${var:-defaultvalue}"
# how to iterate arrays
# for f in "${my_array[@]}"; do ... done
# array length
# ${#my_array[@]}
#####################################################
#!!!!!!!!! useful lib functions !!!!!!!!!!!!!!!!!!!!!
## Use it instead of echo!!!
println() {
printf '%s\n' "$*"
}
# verbose exit
function die {
>&2 echo "Fatal: ${*}"
exit 1
}
# Split string by separator
# $1=separator $2=string
split_string(){
array=()
while read -rd "$1" i; do
array+=("$i")
done < <(printf '%s%s' "$2" "$1")
array
}
# Print error message
err() {
printf '%s\n' "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
}
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#
# More (un)useful functions
#
calc() {
local exprs
exprs="$1"
echo "scale=10; ${exprs}" | bc -l
}
floor() {
local exprs
exprs="$1"
printf "%.0f" "$exprs"
}
# recommended
[[ "${BASH_VERSINFO[0]}" -lt 4 ]] && die "Bash >=4 required"
# Just to remember how to do things
#
delete_me(){ ###############################################
while read -r f; do
println "file=${f}"
done < <(find /tmp)
[[ "filename" =~ ^[[:alnum:]]+name ]] # true
[[ "filename" == "f*" ]] # false
[[ "${v}" == "str" ]] # compare!
[[ -z "${my_var}" ]] # empty? (-n = not empty)
(( my_var > 3 )) || [[ "${my_var}" -gt 3 ]]
(( i = 10 * j + 400 )) # assign!
declare -a flags
flags=(--foo --bar='baz') # assign array
flags+=(--greeting="Hello ${name}") # push into array
readarray -t lines < <(command) # command -> array
for z in "${zs[@]}"; do yes; done # iterate array
local -i hundred=$(( 10 * 10 )) # declare INT local variable
local my_var="$(my_func)" # !! $?=0 ALWAYS!
tar -cf - ./* | ( cd "${DIR}" && tar -xf - )
ret=( "${PIPESTATUS[@]}" ) # ret[0], ret[1] exit codes!
# PROCESS OPTIONS
while [[ "$1" =~ ^- && ! "$1" == "--" ]]; do case $1 in
-V | --version )
echo $version
exit
;;
-s | --string )
shift; string=$1
;;
-f | --flag )
flag=1
;;
esac; shift; done
if [[ "$1" == '--' ]]; then shift; fi
} ##########################################################
# vim: set tabstop=2:softtabstop=2:shiftwidth=2:noexpandtab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment