Skip to content
shellmap

bang-bangHistory expansion `!!` — repeat the previous command across all 5 shells

Equivalents in every shell

Bashunix
!!

Bang-bang expands at PARSE time to the previous command line, then bash re-prints and runs it. Common idiom: `sudo !!` reruns the last command with sudo. `history -p '!!'` shows what would expand without running. Disable history expansion entirely with `set +H` if `!` keeps biting you in passwords / URLs.

Zshunix
!!

Same POSIX history-expansion grammar as bash; zsh also accepts the `r` builtin and `fc -e -` as fc-style alternatives. The `Esc-.` keystroke inserts the LAST argument inline (preview before running) — usually nicer than blind `!!`. Disable bang expansion with `setopt no_bang_hist` if it surprises you.

Fishunix
$history[1] | source

Fish dropped POSIX `!!` deliberately as of 3.0 — the modern UX is Up-arrow + Enter (with autosuggest history). For scripted re-run, `eval $history[1]` works but fires unconditionally. `bind \e\[A history-prefix-search-backward` gives prefix-aware history search.

PowerShellwindows
Invoke-History

No `!!` operator. `Invoke-History` (alias `r`) replays the LAST command from `Get-History`; `Invoke-History 7` replays history entry 7. PSReadLine's `Ctrl-R` does interactive reverse-i-search, the modern equivalent muscle-memory for bang-bang users.

cmd.exewindows
F3

cmd.exe has no bang expansion. Press `F3` to recall the entire last command, or `F8` for prefix-match scrolling backwards through doskey history. `doskey /history` lists the buffer; there is no scriptable in-line replay operator.

Worked examples

Re-run the previous command with sudo (the canonical bang-bang use)

Bash
sudo !!
Zsh
sudo !!
Fish
sudo $history[1]
PowerShell
Start-Process pwsh -Verb RunAs -ArgumentList "-c", (Get-History -Count 1).CommandLine

Preview the expansion without executing (verify before damage)

Bash
history -p '!!'
Zsh
print -r -- !!:p
PowerShell
(Get-History -Count 1).CommandLine

Replay the last command unmodified

Bash
!!
Zsh
!!
PowerShell
r
cmd.exe
F3

Gotchas

  • Bash history expansion fires inside DOUBLE-quoted strings too — `echo "Hello !!"` will substitute the previous command, breaking the literal. Single-quote or `\!` to escape. The single most common gotcha when pasting URLs / passwords containing `!` into bash.
  • Bang expansion happens BEFORE `set -e` / safety guards take effect — a typo like `!ls` matching a destructive recent command (`!rm`) will run with no confirmation. The defensive habit is the `:p` modifier (`!!:p` — print-don't-execute) before committing to the dangerous form.
  • In fish, `!!` is parsed as two literal `!` characters and ignored — you will silently get nothing instead of the previous command. The fish way is the Up-arrow autosuggestion or `$history[1]`. Bash muscle memory will quietly fail rather than error in fish.
  • PowerShell `Get-History` is per-session by default — closing pwsh loses it. PSReadLine's `Get-PSReadLineOption | Select HistorySavePath` enables persistent history; the path is OS-specific (`%APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\` on Windows, `~/.local/share/powershell/PSReadLine/` on Linux/macOS).
  • cmd.exe `doskey` history dies with the cmd window. There is no on-disk persistence and no `!!` operator — keyboard-only recall via `F3`/`F7`/`F8`. Scripts cannot programmatically re-run "the last command" in cmd; this is one of the genuine gaps PowerShell was built to close.

WSL & PowerShell Core notes

pwshPSReadLine ships with PowerShell 5.1+ on Windows and is bundled in pwsh 7+ across all platforms — `Ctrl-R` (reverse-search), `F8` (prefix-search), `Up`/`Down` (history scroll) work identically on Windows / macOS / Linux. The `Invoke-History` cmdlet is also cross-platform.
WSLInside WSL, bang-bang behaves exactly as on Linux — bash/zsh history expansion is process-local. From Windows pwsh, `wsl !!` does NOT work (pwsh has no `!!` operator and does not pass `!` through interop in a way wsl bash can re-expand). The reliable cross-boundary pattern is `(Get-History -Count 1).CommandLine | Set-Clipboard` then paste into wsl.

Related commands