Variables, conditionals, and loops
The core building blocks every real script is made of. · 11 min
A bash script is just a text file of shell commands, made executable and run directly — starting with a "shebang" line (`#!/bin/bash`) that tells the system which interpreter to run it with. Variables are assigned with no spaces around `=` (`name="value"`) and referenced with `$name` or `${name}` (the braces version avoids ambiguity when the variable name is adjacent to other text, like `${name}_backup`). Unlike many languages, bash variables are untyped strings by default — arithmetic requires explicit syntax like `$((a + b))` or the `let` builtin.
Conditionals use `if`/`then`/`elif`/`else`/`fi`, commonly paired with the `[[ ... ]]` test construct (the modern, more forgiving alternative to the older single-bracket `[ ... ]`): `if [[ -f "$file" ]]; then` tests whether a file exists, `if [[ "$a" == "$b" ]]; then` tests string equality, `if [[ $count -gt 10 ]]; then` tests numeric comparison — note `-gt`/`-lt`/`-eq` for numbers versus `==`/`!=` for strings, a common source of subtle bugs when the wrong comparison operator is used for the data type.
Loops iterate: `for item in list; do ... done` walks a fixed list or the output of a command; `while [[ condition ]]; do ... done` continues as long as a condition holds, useful for polling or reading input line by line. A pattern you'll use constantly: `for file in *.log; do ... done` to process every matching file in a directory without hard-coding filenames.
| Command | Purpose | Example |
|---|---|---|
| chmod +x script.sh | Make a script executable | — |
| ./script.sh | Run an executable script in the current directory (the ./ is required — see Level 2) | — |
| bash script.sh | Run a script explicitly with bash, regardless of its own permissions or shebang | — |
A minimal script combining all three
#!/bin/bash
for file in /var/log/*.log; do
size=$(stat -c%s "$file")
if [[ $size -gt 104857600 ]]; then
echo "WARNING: $file is over 100MB ($size bytes)"
fi
doneCommon Mistakes
- ⚠ Using `==` for numeric comparison instead of `-eq`, or `-eq` for string comparison instead of `==` — bash won't always error clearly, it may just silently produce the wrong result
- ⚠ Forgetting to quote variables (`$file` instead of `"$file"`) — this breaks on filenames containing spaces, one of the single most common real bash bugs
- ⚠ Forgetting `chmod +x` and then being confused why `./script.sh` gives "permission denied"
Takeaway: Quote your variables (`"$file"`, not `$file`) essentially everywhere — the single most common real-world bash bug is a script that works fine until it meets a filename with a space in it.