Meet the quoting and subshell traps head on
Task
Reproduce the four bash traps that produce silent wrong answers rather than errors: the subshell that discards a loop counter, the unquoted variable, the [ that creates a file, and the destructive expansion of an unset variable. Seeing each fail is worth more than reading the rule.
Steps
- The subshell counter: run
n=0; printf 'a\nb\nc\n' | while read x; do n=$((n+1)); done; echo $nand observe it prints 0. Then fix it with a redirect (done < <(printf ...)) and observe 3. Explain the subshell. - The unquoted variable: create a file named
two words.txt, thenf="two words.txt"; ls $ffails looking for two files, whilels "$f"works. - The
[file trap: run[ 5 > 3 ]and thenls-- confirm a file named3now exists, and explain that>was redirection. Show[ 5 -gt 3 ]is the correct numeric test. - The destructive expansion: create a subdirectory with a file, then demonstrate SAFELY why
rm -rf "$dir"/is dangerous withdirunset -- useecho rm -rf "${dir}/"(with echo, so nothing is deleted) and see it expand torm -rf /. Then show${dir:?}refusing. - Add
set -euo pipefailto a small script and show it catching an unset variable and a failing pipeline stage that the default would have ignored. - Show
$(...)nesting where backticks would need escaping.
Verify
cd ~/lab-bash
n=0; while read x; do n=$((n+1)); done < <(printf 'a\nb\nc\n'); test "$n" = 3 && echo "redirect keeps the counter"
test -f 3 && echo "[ 5 > 3 ] created a file called 3" && rm -f 3
unset dir; ( set -u; echo "safe: ${dir:?must be set}" ) 2>&1 | grep -qi 'must be set' && echo "guard refused empty var"
The counter reaching 3 only with the redirect, and the file named 3 existing after [ 5 > 3 ], are the two that stick. Both are silent in normal use: no error, just a wrong answer or a stray file.
Notes
Every trap here fails quietly. That is the whole reason to meet them deliberately: a syntax error announces itself, but a subshell eating your counter or a string comparison masquerading as numeric just gives you the wrong number, and you find out much later.