shellcheck.net
Also, advanced bash is mostly about structuring code for maintainability, exception handling and some good tidbit functions you can easily adapt. Actually a good experience for creating maintianable lower-level code too.
That said, i have a (POSIX) cheatsheet i still regularly use. Most important parts:
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## exit codes for GNU/Linux
┌──────────┬────────────────────────────────────────────────────────┬─────────────────────────────────────┐
│ Exitcode │ Meaning │ Example │
├──────────┼────────────────────────────────────────────────────────┼─────────────────────────────────────┤
│ 1 │ Catchall for general errors, such as "divide by zero" │ let "var1 = 1/0" │
│ 2 │ Misuse of shell builtins: Missing keyword or command. │ empty_function() {} │
│ 126 │ cannot invoke requested command │ /dev/null │
│ 127 │ A utility to be executed was not found │ evho │
│ 128 │ Invalid argument to exit: only integer args in the │ exit 3.14159 │
│ │ range 0 - 255 allowed │ │
│ 128+n │ A command was interrupted by signal n (128 + n) │ kill -9 $PPID returns 137 (128 + 9) │
│ 130 │ Script terminated by Ctrl+C: fatal error signal 2, │ Ctl-C │
│ │ (130 = 128 + 2, see above) │ │
│ 255* │ Exit status out of range: exit takes only integer args │ exit -1 │
│ │ in the range 0 - 255 │ │
└──────────┴────────────────────────────────────────────────────────┴─────────────────────────────────────┘
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Numeric True/False
OR ||:
1 + 1 = 1 TRUE || TRUE = TRUE
1 + 0 = 1 TRUE || FALSE = TRUE
0 + 0 = 0 FALSE || FALSE = FALSE
AND &&:
1 * 1 = 1 TRUE && TRUE = TRUE
1 * 0 = 0 TRUE && FALSE = FALSE
0 * 0 = 0 FALSE && FALSE = FALSE
Btw; lowercase true/false are special in that they set the respective state, standalone or as argument.
Said state can be set to variables too, for constructs like: var=true; $var && echo True
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Variable-Expansion
┌───────────────────────┬───────┬───────┬───────────┐
│ VAR is: │ unset │ empty │ non-empty │
├───────────────────────┼───────┼───────┼───────────┤
│ [ -z "${VAR}" ] │ true │ true │ false │
│ [ -z "${VAR+set}" ] │ true │ false │ false │
│ [ -z "${VAR-unset}" ] │ false │ true │ false │
│ [ -n "${VAR}" ] │ false │ false │ true │
│ [ -n "${VAR+set}" ] │ false │ true │ true │
│ [ -n "${VAR-unset}" ] │ true │ false │ true │
└───────────────────────┴───────┴───────┴───────────┘
Btw,
[ -z $var ] &&
[ -n $var ] ||
are *not* the same; the first ist exact match, rather false, the second forgiving, rather true.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Parameter expansion
# Use these in place of awk or sed calls when possible
┌─────────────────────────┬─────────────────────────────────────────────┐
│ Parameter │ Description │
├─────────────────────────┼─────────────────────────────────────────────┤
│ ${VAR/PATTERN/REPLACE} │ Substitute first pattern with replacement │
│ ${VAR//PATTERN/REPLACE} │ Substitute all pattern with replacement │
│ ${VAR#PATTERN} │ Remove shortest match of pattern from start │
│ ${VAR##PATTERN} │ Remove longest match of pattern from start │
│ ${VAR%PATTERN} │ Remove shortest match of pattern from end │
│ ${VAR%%PATTERN} │ Remove longest match of pattern from end │
│ ${#VAR} │ Length of var in characters │
└─────────────────────────┴─────────────────────────────────────────────┘
Summary:
* String manipulation with ${VAR#PREFIX}, ${VAR##PREFIX}, ${VAR%SUFFIX} and ${VAR%%SUFFIX}.
* Conditional treatment of unset variables with ${VAR-DEFAULT}, ${VAR=DEFAULT}, ${VAR+FALLBACK}
and ${VAR?MESSAGE} as well as the unset-or-empty variants with :-, :=, :+ and :?.
* Variable length with ${#VAR}.
filename=/foo/bar.baz
"${filename%/*}" # /foo # dirname
"${filename%.*}" # /foo/bar # filename
"${filename##*/}" # bar.baz # basename
"${filename##*.}" # baz # file-ext
Btw, if it goes over 100 to 150 loc, go Python at least. No matter how disciplined you are or how clean your code is, it gets messy.