Here are my notes on writing Bash scripts. It's opinionated and does not cover everything you need to know about scripting in Bash. I wrote this as an avid user of Bash, both as a shell and for scripting. Writing scripts in Bash can sometimes be challenging due to a somewhat arcane syntax, and there are several pitfalls to be aware of. Regardless, I enjoy writing scripts in Bash.
Following a Style Guideline help keeping scripts consistent, which improves readability and eases maintainability. A guideline also help enforce best pratices, ensuring safe and robust scripts. In a team, the guideline facilitates collaboration and assist in onboarding new developers.
Below are my minimal and opinionated list of rules to follow, when writing Bash scripts.
The first rule, that allows you to not follow the guidelines:
Formatting rules:
Preamble rules:
Example of a preable:
#!/usr/bin/env bash # Send an email message if the disk is almost full set -euo pipefail
Naming rules:
Documentation and Comment rules:
Linting rules:
Example on disabling a check:
# shellcheck disable=SC1090 # we need a non-constant source here source "$config_file"
Note that it's a good idea to comment why the check is disabled.
The following will truncates the file file.txt to zero size:
: > file.txt
The Bash built-in : is a no-op with a return code of 0.
See https://superuser.com/a/90061
The trap command is a powerfull built-in.
TMPDIR="$(mktemp -d)"; readonly TMPDIR; trap 'rm -rf -- "$TMPDIR"' EXIT
Putting the following at the top of a script will prevent the user in killing a script by pressing Ctrl-C. It will also disable echoing of "^C" when Ctrl-C is pressed while the script runs.
trap '' INT STTY=$(stty -g); readonly STTY; stty -ctlecho; trap 'stty $STTY' EXIT
Putting the following at the top of a script will ensure that the user will be returned to their current working directory (CWD) when the script exits. In other words, this makes it safe to change directory in the script.
CWD=$(cd "$(dirname "$0")" && pwd); readonly CWD; trap 'cd "$CWD"' EXIT
read -rsp $'Press any key to continue...\n' -n1 _key
When running the follwowing, you'll be asked to confirm if it should run. If you need to run this from, e.g., CI, you can add the --yes option and it will run.
#!/usr/bin/env bash
rval=-1
case $# in
0) echo "This is a demo!"
read -r -p "Are you sure you want to continue? [y/N] " ans
[[ ! ${ans,,} =~ ^(yes|y)$ ]] && msg="Bailing out..." && rval=0
;;
1) [[ ! $1 =~ ^(--yes|-y)$ ]] && msg="Unknown option: $1" && rval=1
;;
*) msg="Too many options: $#" && rval=1
;;
esac
[[ $rval -ne -1 ]] && echo "$msg" && exit $rval
echo "Doing stuff.."
Below are some Bash references that I find usefull.
Copyright ©2023-2025 Søren Lund
Last modified on Friday, Oct 17, 2025