Bash › Bash Fundamentals

Bash variables, quoting, and script structure

4 min read Beginner 4 sections

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?

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.

Was this lesson helpful?