The history command in Linux
The shell records every command you run, and history prints that record. The real productivity is in the shortcuts around it: Ctrl+R searches as you type, !! repeats the last command (sudo !! is legendary), and !$ reuses the last argument. Learning three of these tricks saves more keystrokes than any alias.
How history works
The shell appends each command you run to an in-memory list; on exit, that list is written to $HISTFILE (~/.bash_history). Both ends are tunable — HISTSIZE for memory, HISTFILESIZE for disk — and the write-on-exit model explains the classic confusion: two concurrent terminals do not see each other's commands, and the last shell to exit can clobber what earlier ones wrote. history -a (append continuously, often wired into PROMPT_COMMAND) is the standard cure.
The interactive magic is layered on top by readline, the line-editing library bash shares with dozens of tools — Ctrl+R incremental search is readline reading the history list. The ! expansions (!!, !$, ^old^new) are yet another layer: history expansion, performed by the shell before parsing, which is why they compose with anything (sudo !!) and why a literal exclamation mark in a double-quoted string can surprise you. Three mechanisms, one seamless illusion of memory.
Syntax
history [N] Common options
| Option | What it does |
|---|---|
history 20 | The last 20 commands. |
Ctrl+R | Interactive reverse search: type any part of an old command. |
!! | Repeat the previous command. |
!$ | The last argument of the previous command. |
!123 | Re-run command number 123 from the list. |
history -c | Clear the in-memory history. |
How to use history: examples
$ history | grep ssh Find that server address you connected to last week.
$ sudo !! Forgot sudo? Repeat the exact previous command with it.
$ mkdir -p projects/new-idea && cd !$ !$ expands to the last argument — create a directory and enter it without retyping the path.
$ ^http^https Quick substitution: re-run the previous command replacing http with https.
$ HISTTIMEFORMAT="%F %T " history Show timestamps next to each command (set it in .bashrc to make it permanent).
Real-world use cases for history
Reconstructing what you did
After an incident: HISTTIMEFORMAT="%F %T " history | grep -E "systemctl|nginx" shows exactly which service commands ran and when — your own audit trail for the postmortem timeline.
Turning history into documentation
Solved a gnarly setup after an hour of trial and error? history | tail -40 > setup-notes.sh captures the session; clean it up and you have a runbook. Most good ops documentation starts life as harvested history.
Pro tips and common mistakes
- Ctrl+R, fragment, Enter — the reverse-search habit that outvalues every alias you will ever write.
- Grow the history: HISTSIZE=100000 and HISTFILESIZE=200000 in .bashrc; disk is free, forgotten commands are not.
- HISTCONTROL=ignoredups:ignorespace skips duplicates and lets a leading space keep secrets out of the record.
- Fix a typo fast: ^wrong^right re-runs the previous command with the substitution applied.
Frequently asked questions about history
How do I search my command history?
Press Ctrl+R and start typing any fragment; keep pressing Ctrl+R to cycle through older matches, Enter to run, Esc to edit first. For a full list, history | grep term.
Why are commands from another terminal missing?
Each shell keeps history in memory and writes the file on exit, so concurrent sessions don't see each other until then. Bash can share more aggressively with history -a via PROMPT_COMMAND.
How do I keep a command out of history?
With HISTCONTROL=ignorespace set (default on many distros), any command that starts with a space is not recorded — useful when a command contains a secret.
Related commands
Find lines matching a pattern in files or piped input — the workhorse of text search.
echoPrint text and variables, and write or append to files with > and >>.