Code of the Day
IntermediateScripting patterns

Lab: Scripting patterns

Hands-on quiz challenges covering conditionals, loops, functions, and exit codes from the Scripting patterns module.

Lab · optionalBashIntermediate15 min
Recommended first
By the end of this lesson you will be able to:
  • Identify [[ ]] pitfalls and correct loop patterns
  • Reason about function scope and variable leakage
  • Predict the behaviour of set -e in edge cases

This lab consolidates everything from the Scripting patterns module. Work through the questions, then try the "Do it yourself" challenges in a real terminal.

Conditionals and test syntax

  1. 1.
    Which expression correctly tests that a variable $f is non-empty AND refers to an executable file?
  2. 2.
    The expression [[ $unset_var = "" ]] is safe even when set -u is active.
  3. 3.
    After [[ "v1.2.3" =~ ^v([0-9]+)\.([0-9]+) ]], what is the value of ${BASH_REMATCH[2]}?

Loop patterns

  1. 1.
    You run: for f in *.txt; do echo "$f"; done in a directory with no .txt files (and nullglob is not set). What happens?
  2. 2.
    A pipeline: some_command | while IFS= read -r line; do count=$((count+1)); done. After the loop, $count is 0. Why?
  3. 3.
    break 2 inside a nested for loop exits only the inner loop, leaving the outer loop running.

Functions and scope

  1. 1.
    A function sets tmp=$(mktemp) without local. The caller also uses $tmp. What is the risk?
  2. 2.
    get_user() { echo "alice"; return 42; }. You run: name=$(get_user); echo $?. What does $? print?

set -e behaviour

  1. 1.
    With set -e active, which of these does NOT cause the script to exit on failure?
  2. 2.
    trap EXIT fires even if the script exits due to set -e catching a failed command.

Do it yourself

Put all four topics to work in a single script:

#!/usr/bin/env bash
set -euo pipefail

# Cleanup trap
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT

# Function with local variable
make_report() {
  local dir=$1
  local count=0
  while IFS= read -r line; do
    count=$((count + 1))
  done < <(ls "$dir")
  echo "$count files in $dir"
}

# Conditional guarding the work
if [[ -d "$tmpdir" && -w "$tmpdir" ]]; then
  touch "$tmpdir/a.txt" "$tmpdir/b.txt" "$tmpdir/c.txt"
  make_report "$tmpdir"
fi

# Loop over the files
for f in "$tmpdir"/*.txt; do
  [[ -f "$f" ]] || continue
  echo "File: $(basename "$f")"
done

Save it, chmod +x it, and run it. Then try breaking it deliberately: remove local, remove set -u, or use | instead of < <(...) for the while read loop and observe the difference.

Where to go next

Scripting patterns are solid. Next up: the Text processing module — grep, sed, awk, cut, sort, and uniq — where the real text-manipulation power of the Unix toolkit lives.

Finished reading? Mark it complete to track your progress.

On this page