Shell Scripting & Automation

Write reliable POSIX shell scripts — variables, conditionals, loops, functions, exit codes, and the quoting rules that keep automation from breaking in production.

Medium 55m 3 tasks

Learning Objectives

  • Write a shell script with a proper shebang and understand how the OS uses it
  • Use variables, positional parameters ($1, $@, $#), and command substitution safely
  • Implement conditionals (if/case) and loops (for/while) in shell scripts
  • Explain exit codes and use them for error handling in automation
  • Apply quoting rules to avoid word-splitting and globbing bugs

Why Script Instead of Typing Commands

A script turns a fragile sequence of manual steps into something repeatable, reviewable, and safe to run at 3am by someone who isn't you. Every production automation pipeline — CI/CD, cron jobs, deployment tooling — is built on the same shell-scripting fundamentals.

Anatomy of a Script

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

echo "Backing up $1..."
  • The shebang (#!/usr/bin/env bash) tells the kernel which interpreter runs the rest of the file. Using env bash instead of a hardcoded /bin/bash path is more portable across systems where bash lives in a different location.
  • set -e — exit immediately if any command fails, instead of silently continuing
  • set -u — treat any unset variable as an error, catching typos before they cause damage
  • set -o pipefail — a pipeline's exit code reflects the first failing command, not just the last one

Variables and Quoting

name="alice"        # no spaces around =
echo "$name"         # always quote expansions

Unquoted variables are word-split and glob-expanded by the shell. A variable holding my file.txt becomes two separate arguments (my and file.txt) if left unquoted — a classic source of scripts that "work on my machine" and break on real data.

Positional parameters: $1, $2, ... are the script's arguments; $@ is all of them; $# is the count; $0 is the script's own name.

Conditionals

if [ -d "$SRC" ]; then
  echo "Directory exists"
else
  echo "Missing: $SRC" >&2
  exit 1
fi

Common test operators: -f (regular file exists), -d (directory exists), -z (string is empty), -eq/-ne (numeric equality).

A case statement branches cleanly on multiple string patterns without a long if/elif chain:

case "$env" in
  prod)  echo "careful!";;
  staging|dev) echo "safe to experiment";;
  *) echo "unknown environment"; exit 1;;
esac

Loops

for env in dev staging prod; do
  echo "Deploying to $env"
done

while read -r line; do
  echo "Processing: $line"
done < input.txt

while read -r line; do ... done < file is the safe way to process a file line-by-line — it doesn't word-split or glob-expand each line, unlike for line in $(cat file).

Functions

backup_dir() {
  local target="$1"
  tar -czf "${target}.tar.gz" "$target"
}

local scopes a variable to the function — without it, every variable is global and can silently clobber a caller's state.

Exit Codes

Code Meaning
0 Success
1 General error
126 Command found but not executable
127 Command not found
130 Terminated by Ctrl+C (SIGINT)

Exit codes are how scripts communicate success/failure to whatever calls them — if my_script.sh; then ... branches on exactly this.

Common Pitfalls

  • Unquoted variables causing word-splitting (rm $DIR/* with an unset or empty $DIR can expand dangerously)
  • Assuming == works the same in every shell — it's a bash-ism, POSIX sh only guarantees =
  • set -e doesn't always do what people expect inside conditionals or the middle of a pipeline — test your assumptions
  • Forgetting execute permission (chmod +x script.sh) before trying to run a script directly

The very first line of a script isn't a comment to humans — it's an instruction to the kernel about which program should execute the rest of the file.

✦ Answer the questions to complete this task

What is the purpose of the shebang line at the top of a script?

Different exit codes carry different, widely-agreed meanings that automation tooling relies on.

✦ Answer the questions to complete this task

What exit code conventionally means 'command not found'?

The shell splits unquoted variable expansions on whitespace and expands glob characters like * before your script ever sees the value.

✦ Answer the questions to complete this task

Why should you write "$file" instead of $file when the variable might contain a space?

💪 Exercises & Challenges

📝 MCQ Medium +20 XP

Shell Scripting & Automation MCQ

Test your understanding of Shell Scripting & Automation.

Start →
⚙️ Practical Medium +30 XP

Harden a Backup Script

You're given a script skeleton that is missing quoting and error handling. Rewrite it, fixing: (1) add a proper shebang, (2) quote every variable expansion, (3) add `set -euo pipefail` right after the

Start →
🚩 Challenge Medium +50 XP

Diagnose the Broken Deploy Script

A junior engineer's deploy script keeps silently continuing even after a failed step, and once corrupted a directory literally named `my backup` because of unquoted variable expansion splitting it int

Start →