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.
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, andCtrl+Rsearch) 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:
- In-Memory History Buffer: Holds commands executed during the active interactive shell session. The capacity of this buffer is governed by the
HISTSIZEenvironment variable (typically default 1000 lines). - 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 byHISTFILESIZE(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 / Option | Function & Operation |
|---|---|
history | Displays the entire numbered command history list |
history 20 | Displays only the last 20 executed commands |
history -c | Clears 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 bothignorespaceandignoredups.erasedups: Purges all previous duplicate occurrences of the command from the entire history list.
HISTTIMEFORMAT: When set (e.g.,export HISTTIMEFORMAT="%F %T "),historyprints 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, enterhistory -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 Designator | Meaning & Action |
|---|---|
!! | Re-executes the immediately preceding command (identical to !-1) |
!n | Re-executes command number n from the history list (e.g., !1042) |
!-n | Re-executes the command executed n lines ago (e.g., !-3) |
!string | Re-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^new | Quick 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 Designator | Meaning & 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 |
!:n | Extracts 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. PressCtrl+R, type search keywords; pressCtrl+Rrepeatedly 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.
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 userbob'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}: UsedefaultifVARis unset or null.${VAR:=default}: AssigndefaulttoVARif unset or null.${VAR:+alternate}: UsealternateifVARis set and not null.${#VAR}: Returns the length in characters of the string value inVAR.${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 ))yields16. - The
letcommand also performs arithmetic:let "x = 10 / 2".
6. Process Substitution
- Makes a running process appear as a file path (using
/dev/fd/Nor 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 Mechanism | Variable Expansion ($VAR) | Command Sub ($(cmd)) | Arithmetic ($(( ))) | Globbing (*, ?) | Word Splitting |
|---|---|---|---|---|---|
Single Quotes ('...') | Disabled (Literal) | Disabled (Literal) | Disabled (Literal) | Disabled | Disabled |
Double Quotes ("...") | Enabled | Enabled | Enabled | Disabled | Disabled |
Backslash (\char) | Escapes $ | Escapes ` | Escapes $(( | Escapes *, ? | N/A |
| No Quotes (Bare) | Enabled | Enabled | Enabled | Enabled | Enabled |
Which history expansion shortcut repeats the immediately preceding command while substituting the first occurrence of 'test' with 'prod'?
In the standard 9-stage Bash expansion pipeline, which expansion stage is executed FIRST before all others?
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?