Watch someone backspace 40 characters instead of pressing CTRL+W, and you’ll understand why this list exists. A collection of shell tricks-grouped by what works everywhere and what’s Bash/Zsh-speci...
set -e: Exit on error. Very useful, but notoriously weird with edge cases (especially inside conditionals like if statements, while loops, and pipelines). Don’t rely on it blindly as it can create false confidence. (Pro-tip: consider set -euo pipefail for a more robust safety net, but learn its caveats first.)
while I appreciate that the author mentions how weird this is, nobody is going to learn all the caveats correctly. Don’t use set -e. Don’t use set -e. Don’t use set -e. It’s a shit ass broken ass fucked feature that half of nobody understands well. Here’s a great wiki page explaining why it’s trash: https://mywiki.wooledge.org/BashFAQ/105
People like Go, and Go requires you to manually and stupidly handle every possible error case. Why not do the same for shell? It’s really quite easy:
#!/usr/bin/env bashechoerr() { echo"$@" 1>&2; }
die() {
message="$1"; shift
exit_code="${1:-1}"
echoerr "$message"exit"$exit_code"
}
temp_dir="$HOME/tmp"mkdir -p "$temp_dir" || die "Failed to make persistent temporary dir $temp_dir"
lc_dir="$(mktemp -d -p "$temp_dir")" || die "Failed to make target dir in $temp_dir"
Look at that, descriptive error messages! And it doesn’t depend on a shell feature that is inconsistent between versions with no good documentation about all of the fucked up caveats.
You know… I was about to reply with "I use set -e and I love it, but them I read the link and it gave me flashbacks. In a previous work at some points I programmed way more in bash than the languages I was officially hired to program into, and I run in some many of this edge cases, I think almost all of the ones mentioned in the link, including doing the workarounds mentioned. two that standed out to me was local var=$(fail) and if f(). Side note, I remember finding a bug in declare (I don’t remember exactly, but one of the flags, maybe -l to make a local variable was not working) and was só excited to fill a bug report but then I saw that it had already fixed in a newer bash release.
Anyway, In the end if I recall correctly I never settled in a one fixed approach, I distinctly remember adding set -eu to a bunch of scripts but also remember having to set +e in some cases like when sourcing other scripts and also adding the suggested foo || die combo a bunch"
I think in the end my approach was the same as rking’s at the end of the linked text, I used it but not relied on it. And I guess using too much bash made me paranoid and I heavily tested every line for all sorts of error cases. I think set -e is good when debugging when the thing is not working, especially because bash also suffers to lack a good debug and tracing environment, leaving you to set a bunch of stuff just to have a trace of your script and see what it is doing.
I remember a while ago - when, like in your anecdote, I mostly coded in bash - I had a dream that I found out people were invoking my scripts in a manner that essentially overrode settings that might (or, in my case, might not) have been set at the beginning of the script.
This never (AFAIK) happened in waking hours, but I was very offended in the dream.
while I appreciate that the author mentions how weird this is, nobody is going to learn all the caveats correctly. Don’t use
set -e. Don’t useset -e. Don’t useset -e. It’s a shit ass broken ass fucked feature that half of nobody understands well. Here’s a great wiki page explaining why it’s trash: https://mywiki.wooledge.org/BashFAQ/105People like Go, and Go requires you to manually and stupidly handle every possible error case. Why not do the same for shell? It’s really quite easy:
#!/usr/bin/env bash echoerr() { echo "$@" 1>&2; } die() { message="$1"; shift exit_code="${1:-1}" echoerr "$message" exit "$exit_code" } temp_dir="$HOME/tmp" mkdir -p "$temp_dir" || die "Failed to make persistent temporary dir $temp_dir" lc_dir="$(mktemp -d -p "$temp_dir")" || die "Failed to make target dir in $temp_dir"Look at that, descriptive error messages! And it doesn’t depend on a shell feature that is inconsistent between versions with no good documentation about all of the fucked up caveats.
You know… I was about to reply with "I use
set -eand I love it, but them I read the link and it gave me flashbacks. In a previous work at some points I programmed way more in bash than the languages I was officially hired to program into, and I run in some many of this edge cases, I think almost all of the ones mentioned in the link, including doing the workarounds mentioned. two that standed out to me waslocal var=$(fail)andif f(). Side note, I remember finding a bug in declare (I don’t remember exactly, but one of the flags, maybe -l to make a local variable was not working) and was só excited to fill a bug report but then I saw that it had already fixed in a newer bash release.Anyway, In the end if I recall correctly I never settled in a one fixed approach, I distinctly remember adding set -eu to a bunch of scripts but also remember having to set +e in some cases like when sourcing other scripts and also adding the suggested
foo || diecombo a bunch"I think in the end my approach was the same as rking’s at the end of the linked text, I used it but not relied on it. And I guess using too much bash made me paranoid and I heavily tested every line for all sorts of error cases. I think
set -eis good when debugging when the thing is not working, especially because bash also suffers to lack a good debug and tracing environment, leaving you to set a bunch of stuff just to have a trace of your script and see what it is doing.I remember a while ago - when, like in your anecdote, I mostly coded in bash - I had a dream that I found out people were invoking my scripts in a manner that essentially overrode settings that might (or, in my case, might not) have been set at the beginning of the script.
This never (AFAIK) happened in waking hours, but I was very offended in the dream.