Bash › Bash Fundamentals
Bash variables, quoting, and script structure
Now we move from running commands to writing scripts. The fundamentals here — variables, quoting, arguments, exit codes — are small in number but the quoting rules in particular prevent real disasters. Get these right and your scripts behave; get quoting wrong and they break on the first filename with a space.
You'll learn to
- Use variables and command substitution
- Apply the quoting rules that prevent bugs
- Read arguments and check exit codes
Variables and substitution
name="example.com" # assign — NO spaces around =
echo "$name" # use — always with the dollar sign
# Command substitution: capture a command's output:
count=$(grep -c "error" log.txt)
today=$(date +%F)
echo "Found $count errors on $today"
Assign with no spaces around =, use with $. Command substitution $(...) captures the output of a command into a variable — the way you build up data in a script.
Quoting: the rule that saves you
Always quote your variable expansions: "$var", not $var. Without quotes, Bash splits the value on spaces and expands wildcards — which breaks on filenames with spaces and creates security bugs.
file="my report.txt"
rm $file # WRONG: tries to remove 'my' AND 'report.txt'
rm "$file" # RIGHT: removes the one file 'my report.txt'
Arguments and exit codes
#!/usr/bin/env bash
target="$1" # first argument
output="${2:-out.txt}" # second argument, default 'out.txt' if missing
if [ -z "$target" ]; then
echo "usage: $0 <target>"; exit 1 # exit non-zero on error
fi
grep "pattern" file
echo "exit code was: $?" # $? holds the last command's exit code (0 = success)
$1, $2 are positional arguments; $0 is the script name. ${2:-default} supplies a default. $? holds the last command’s exit code — 0 means success, non-zero means failure, which is how you check whether a command worked.
Checkpoint
Why should you write rm '$file' instead of rm $file when file might contain a space?
Without quotes, Bash performs word-splitting on the variable's value: if file is 'my report.txt', rm $file becomes rm my report.txt — two separate arguments, so it tries to delete 'my' and 'report.txt' instead of the one intended file. Quoting with '$file' keeps the value as a single argument. Unquoted expansions also glob, which can cause further unintended behaviour.
Try it yourself
Write a short script that takes a target as its first argument, defaults an output filename if a second argument isn’t given, and errors out with a usage message if no target is supplied. Quote every variable expansion. Test it with and without arguments.
Key takeaways
- Assign with no spaces (NAME=value); expand with $ and always quote: “$var”.
- Command substitution $(…) captures output into a variable.
- $1/$2 are arguments;
${2:-default}supplies defaults; $? is the exit code. - Begin scripts with set -euo pipefail to fail loudly, not silently.
Quick quiz
Next, file operations as security tools — finding, filtering, and inspecting files at scale.