5.2 Command History, Quoting & Expansion (103.1)

Key Takeaways

  • The history built-in manages the in-memory buffer (HISTSIZE) and synchronizes with the on-disk file (HISTFILESIZE, HISTFILE).
  • History event designators (!n, !-n, !string, !$) and substitution (^old^new) provide rapid command reuse on the command line.
  • Interactive history navigation with Ctrl+R performs reverse incremental search, while Ctrl+G aborts the search safely.
  • Bash evaluates command lines through a strict 9-phase expansion sequence: Brace -> Tilde -> Parameter/Variable -> Command Sub -> Arithmetic -> Process Sub -> Word Splitting -> Globbing -> Quote Removal.
  • Single quotes enforce strong literal quoting suppressing all expansions, while double quotes allow variable, command, and arithmetic expansion while preventing globbing and word splitting.
Last updated: August 2026

5.2 Command History, Quoting & Expansion (103.1)

Quick Summary: Efficient command-line operations require mastering the Bash history mechanism (history, HISTCONTROL, event designators like !!, !$, ^old^new, and Ctrl+R search) alongside the deterministic 9-phase shell expansion sequence. Knowing precisely when brace expansion, parameter expansion, command substitution, arithmetic expansion, word splitting, and pathname globbing occur prevents subtle scripting bugs and guarantees mastery of Topic 103.1.


1. Bash History Architecture & the history Command

Bash maintains two distinct storage layers for previously executed commands:

  1. In-Memory History Buffer: Holds commands executed during the active interactive shell session. The capacity of this buffer is governed by the HISTSIZE environment variable (typically default 1000 lines).
  2. On-Disk History File: Persists historical commands across reboots and terminal sessions. The path is defined by HISTFILE (default ~/.bash_history), and the maximum stored lines are governed by HISTFILESIZE (typically default 2000 lines).
Bash History In-Memory vs. On-Disk Workflow:
┌─────────────────────────────────────────────────────────────────────────┐
│ Interactive Shell Session (RAM Buffer: HISTSIZE=1000)                  │
│ • User runs commands -> Appended to in-memory buffer                     │
│ • Read history: history [N]                                             │
│ • Clear in-memory buffer: history -c                                    │
└────────────────────┬───────────────────────────────▲────────────────────┘
                     │ history -w                    │ history -r
                     │ (Auto on shell clean exit)    │ (Auto on shell startup)
                     ▼                               │
┌─────────────────────────────────────────────────────────────────────────┐
│ Persistent Storage File: ~/.bash_history (HISTFILESIZE=2000)            │
└─────────────────────────────────────────────────────────────────────────┘

history Command Options

Command / OptionFunction & Operation
historyDisplays the entire numbered command history list
history 20Displays only the last 20 executed commands
history -cClears the in-memory history list completely
history -d <offset>Deletes the history entry at the specified numeric index offset (e.g., history -d 450)
history -w [file]Writes the current in-memory history buffer to the history file immediately
history -a [file]Appends newly executed commands from the current session to the history file
history -r [file]Reads the history file and appends its contents to the current in-memory history list
history -n [file]Reads lines not already read from the history file into the current buffer

Fine-Tuning History with HISTCONTROL and HISTTIMEFORMAT

  • HISTCONTROL: Controls which commands are recorded:
    • ignorespace: Commands starting with a leading space character are omitted from history.
    • ignoredups: Consecutive identical commands are recorded only once.
    • ignoreboth: Enables both ignorespace and ignoredups.
    • erasedups: Purges all previous duplicate occurrences of the command from the entire history list.
  • HISTTIMEFORMAT: When set (e.g., export HISTTIMEFORMAT="%F %T "), history prints ISO timestamps alongside line numbers.

💡 LPIC-1 Exam Fill-in-the-Blank Alert: When an exam question asks which command option flushes the current in-memory shell history to the history file on disk immediately, the answer is history -w. To clear the current in-memory history list, enter history -c.


2. History Designators & Command-Line Shortcuts

History expansion is triggered by the exclamation mark (!) character (often called the "bang" operator).

Event Designators (Selecting Commands)

Event DesignatorMeaning & Action
!!Re-executes the immediately preceding command (identical to !-1)
!nRe-executes command number n from the history list (e.g., !1042)
!-nRe-executes the command executed n lines ago (e.g., !-3)
!stringRe-executes the most recent command starting with string (e.g., !systemctl)
!?string?Re-executes the most recent command containing string anywhere in the line
^old^newQuick substitution: replaces the first occurrence of old with new in the previous command and executes it (shorthand for !!:s/old/new/)
# Practical demonstration of history shortcuts:
$ systemctl restart apache2
Failed to restart apache2.service: Unit apache2.service not found.

# Quick substitution fixing the daemon name:
$ ^apache2^httpd
systemctl restart httpd

# Re-running the previous command with sudo privileges:
$ sudo !!
sudo systemctl restart httpd

Word Designators (Selecting Arguments)

Word DesignatorMeaning & Action
!$Extracts the last argument of the previous command
!*Extracts all arguments of the previous command (excluding command name)
!^Extracts the first argument of the previous command
!:nExtracts the n-th argument of the previous command (e.g., !:2)
# Creating a deep directory and immediately navigating into it:
$ mkdir -p /var/log/audit/archive/2026
$ cd !$
# Executes: cd /var/log/audit/archive/2026

Interactive Readline Navigation (Keybindings)

  • Ctrl+R: Incremental Reverse Search. Press Ctrl+R, type search keywords; press Ctrl+R repeatedly to cycle through older matches.
  • Ctrl+G: Cancels reverse search and restores the original empty prompt line.
  • Ctrl+O: Executes the currently selected search match and loads the next sequential line from history into the prompt (advance).
  • Ctrl+P / Ctrl+N: Move to Previous / Next command in history (equivalent to Up/Down arrows).
  • Ctrl+A / Ctrl+E: Move cursor to Beginning (Ctrl+A) or End (Ctrl+E) of current line.
Loading diagram...
The Deterministic 9-Stage Bash Expansion Pipeline

3. The Complete Bash Expansion Sequence

Before executing any command line, Bash parses and transforms tokens through a strict, non-negotiable 9-stage expansion sequence. The ordering is heavily tested on LPIC-1.

1. Brace Expansion

  • Generates arbitrary string combinations before variable or pathname expansion.
  • Syntax: {string1,string2,...} or {start..end[..step]}.
  • Examples:
    echo file_{A,B,C}.txt       # file_A.txt file_B.txt file_C.txt
    echo {1..5}                 # 1 2 3 4 5
    echo {01..10..2}            # 01 03 05 07 09
    mkdir -p project/{src,bin,doc,tests}
    
  • Crucial Rule: Brace expansion does not require files to exist on disk; it is pure string generation.

2. Tilde Expansion

  • Resolves user home directories:
    • ~: Expands to current user's $HOME (/home/alice).
    • ~bob: Expands to user bob's home directory (/home/bob).
    • ~+: Expands to current working directory ($PWD).
    • ~-: Expands to previous working directory ($OLDPWD).

3. Parameter and Variable Expansion

  • Replaces variable names with values.
  • Advanced parameter manipulation syntax:
    • ${VAR:-default}: Use default if VAR is unset or null.
    • ${VAR:=default}: Assign default to VAR if unset or null.
    • ${VAR:+alternate}: Use alternate if VAR is set and not null.
    • ${#VAR}: Returns the length in characters of the string value in VAR.
    • ${VAR#pattern}: Removes shortest matching prefix pattern.
    • ${VAR##pattern}: Removes longest matching prefix pattern.
    • ${VAR%pattern}: Removes shortest matching suffix pattern.
    • ${VAR%%pattern}: Removes longest matching suffix pattern.

4. Command Substitution

  • Replaces command invocation with its standard output (trailing newlines stripped).
  • Modern syntax: $(command) (supports clean, infinite recursive nesting: $(cat $(find /etc -name *.conf)))
  • Legacy syntax: `command` (backticks; nesting requires escaping \command``).

5. Arithmetic Expansion

  • Evaluates integer mathematical expressions inside $(( expression )).
  • Supports standard C arithmetic, bitwise operators, and variables without leading $: echo $(( (5 + 3) * 2 )) yields 16.
  • The let command also performs arithmetic: let "x = 10 / 2".

6. Process Substitution

  • Makes a running process appear as a file path (using /dev/fd/N or named pipes FIFO).
  • <(command): Reading from command output as a file.
  • >(command): Writing to command input as a file.
  • Example: diff -u <(sort file1.txt) <(sort file2.txt)

7. Word Splitting

  • The shell scans the results of unquoted parameter expansions, command substitutions, and arithmetic expansions for word boundaries.
  • Word boundaries are defined by the Internal Field Separator variable $IFS (default: space, tab, newline).
  • Crucial Rule: Word splitting does not occur inside double quotes ("$VAR").

8. Pathname Expansion (Globbing)

  • Scans words for wildcard characters and replaces them with alphabetically sorted matching filenames on disk:
    • *: Matches any string of characters, including empty string.
    • ?: Matches any single character.
    • [...]: Matches any one character enclosed within brackets.
    • [!...] or [^...]: Matches any character not enclosed within brackets.
    • [0-9], [a-z]: Character ranges.
    • POSIX Character Classes: [[:alpha:]] (letters), [[:digit:]] (numbers 0-9), [[:alnum:]] (alphanumeric), [[:space:]] (whitespace), [[:upper:]], [[:lower:]].

9. Quote Removal

  • All unquoted occurrences of \, ', and " that were not result of earlier expansions are stripped from the command line before final execution.

4. Quoting Rules Summary Matrix

Quoting MechanismVariable Expansion ($VAR)Command Sub ($(cmd))Arithmetic ($(( )))Globbing (*, ?)Word Splitting
Single Quotes ('...')Disabled (Literal)Disabled (Literal)Disabled (Literal)DisabledDisabled
Double Quotes ("...")EnabledEnabledEnabledDisabledDisabled
Backslash (\char)Escapes $Escapes `Escapes $((Escapes *, ?N/A
No Quotes (Bare)EnabledEnabledEnabledEnabledEnabled
Test Your Knowledge

Which history expansion shortcut repeats the immediately preceding command while substituting the first occurrence of 'test' with 'prod'?

A
B
C
D
Test Your Knowledge

In the standard 9-stage Bash expansion pipeline, which expansion stage is executed FIRST before all others?

A
B
C
D
Test Your Knowledge

An administrator runs ls [![:digit:]]* in a directory containing the files 1report.txt, annual.txt, 2024log, and notes. Which files does the shell's pathname expansion match?

A
B
C
D