Short answer: The shortcuts that save the most time in Bash and Zsh are Ctrl+A and Ctrl+E to jump along the line, and Ctrl+U, Ctrl+K and Ctrl+W to delete. Ctrl+R searches history, Alt+. inserts the last argument and !! repeats the last command. For jobs, Ctrl+Z suspends and bg resumes in the background. Learn redirection (2>&1, <<<, <(...)), brace expansion and tmux for sessions that survive a dropped SSH connection.
The examples in this terminal cheat sheet were run with GNU Bash 5.2.21 and tmux 3.4 on 9 October 2026. Readline bindings were read from bind -p, and the tmux keys from tmux list-keys. Zsh, screen and the terminal apps were not available for testing, so those rows were checked against their documentation.
Table of Contents
Editing the command line
Bash uses the GNU Readline library in emacs mode by default; Zsh’s line editor uses the same keys. Alt is the Meta key: if Alt does nothing on a Mac, see the terminal app section below.
| Keys | Action |
|---|---|
| Ctrl+A / Ctrl+E | Start / end of the line |
| Alt+B / Alt+F | Back / forward one word |
| Ctrl+U | Delete from the cursor to the start of the line |
| Ctrl+K | Delete from the cursor to the end of the line |
| Ctrl+W / Alt+D | Delete the word before / after the cursor |
| Ctrl+Y / Alt+Y | Paste the last deleted text / cycle through older deletions |
| Ctrl+_ (or Ctrl+X Ctrl+U) | Undo |
| Ctrl+T / Alt+T | Swap two characters / two words |
| Alt+U / Alt+L / Alt+C | Uppercase / lowercase / capitalise the next word |
| Ctrl+L | Clear the screen, keep the current line |
| Ctrl+X Ctrl+E | Open the line in $VISUAL or $EDITOR; it runs when you save and quit |
| Alt+# | Comment out the line and save it to history without running it |
| Tab, Tab Tab | Complete; list the possibilities |
set -o vi / set -o emacs | Switch to vi or back to emacs keys. bind -p lists every binding |
History search and reuse
| Keys or command | Action |
|---|---|
| Ctrl+R | Search history backwards as you type; Ctrl+R again for older matches |
| Ctrl+S | Search forwards. Most terminals grab it for flow control, so run stty -ixon first |
| Ctrl+G | Leave the search without running anything |
| Ctrl+P / Ctrl+N (or Up / Down) | Previous / next command |
| Alt+. (or Alt+_) | Insert the last argument of the previous command; repeat to go further back |
| Ctrl+O | Run the current history line and load the next one; good for replaying a sequence |
history 20 | Last 20 commands with numbers |
HISTCONTROL=ignoreboth | Skip duplicates and lines starting with a space |
HISTTIMEFORMAT='%F %T ' | Show a date and time in history output |
shopt -s histappend | Append to ~/.bash_history instead of overwriting it when several shells exit |
With HISTCONTROL=ignoreboth set, a command typed with a leading space, such as mysql -p'secret', is not saved to history. It still shows in ps while it runs, so keep passwords in option files.
History expansion
| Syntax | Expands to |
|---|---|
!! | The whole previous command |
!$ / !^ | Last / first argument of the previous command |
!:2, !* | Second argument; all arguments |
!42, !-2 | Command number 42; the command two back |
!ssh | The most recent command starting with ssh |
!ssh:p | Print that command without running it (it is added to history, so !! then runs it) |
^gamma^delta | Rerun the previous command with the first gamma replaced by delta |
!!:gs/alpha/omega/ | Rerun with every alpha replaced |
$ cp /etc/nginx/nginx.conf /root/nginx.conf.bak
$ ls -l !$
ls -l /root/nginx.conf.bak
sudo !! repeats the whole previous line with sudo in front, but only the first command of a list gets root. On our test, ls -d /tmp && echo ok became sudo ls -d /tmp && echo ok, where echo ran as the normal user. History expansion works only in interactive shells, not in scripts.
Job control and signals
| Keys or command | Action |
|---|---|
| Ctrl+C | Send SIGINT: interrupt the foreground program |
| Ctrl+Z | Send SIGTSTP: suspend it and get the prompt back |
| Ctrl+D | End of input. On an empty prompt it logs you out |
command & | Start in the background; $! holds its PID |
jobs -l | Background and stopped jobs with PIDs |
fg %1 / bg %1 | Bring job 1 to the foreground / resume it in the background |
wait | Wait for all background jobs to finish |
disown %1 | Remove a job from the shell’s table so it is not sent SIGHUP when you log out |
nohup long-task > task.log 2>&1 & | Start a job that ignores hang-ups from the start |
For server admins: to leave a long job running after you log out of SSH, press Ctrl+Z, then bg, then disown. For planned work, start it inside tmux or screen.
Redirection and pipes
| Syntax | What it does |
|---|---|
cmd > file / cmd >> file | Write stdout to a file / append |
cmd 2> err.log | Write stderr to a file |
cmd > all.log 2>&1 | Both streams to one file. Order matters: 2>&1 > file sends stderr to the terminal |
cmd &> all.log | Bash and Zsh shorthand for the line above |
cmd |& less | Pipe stdout and stderr (same as 2>&1 |) |
set -o noclobber and >| | Refuse to overwrite files with >; >| overrides it once |
cmd <<< "text" | Here-string: a string as stdin |
cat <<EOF ... EOF | Here-document; variables are expanded. Quote it (<<'EOF') to keep $ literal |
diff <(sort a) <(sort b) | Process substitution: command output as a file name |
cmd | tee out.txt | Show output and save it |
a && b, a || b | Run b only if a succeeds / fails |
${PIPESTATUS[@]} | Exit codes of every command in the last pipeline |
set -o pipefail | A pipeline fails if any part fails, not just the last |
$ false | true; echo "status=$? pipestatus=${PIPESTATUS[*]}"
status=0 pipestatus=1 0
$ set -o pipefail; false | true; echo $?
1
Globbing, brace and parameter expansion
| Syntax | Result |
|---|---|
*.log, ?.txt, [ab].log | Any string, one character, one of a set |
shopt -s nullglob | A pattern with no matches expands to nothing instead of itself |
shopt -s globstar then **/*.log | Recursive match through subdirectories |
shopt -s dotglob | Include hidden files in * |
shopt -s extglob then !(*.log), *.@(log|txt) | Everything except .log; .log or .txt. Turn extglob on in an earlier line |
{a,b,c}.conf | a.conf b.conf c.conf |
{01..10..3} | 01 04 07 10 (zero-padded, step 3) |
cp nginx.conf{,.bak} | cp nginx.conf nginx.conf.bak |
mkdir -p site/{css,js,img} | Three directories in one command |
${f##*/}, ${f%/*} | File name and directory of a path |
${f%.log}.bak, ${f/access/error} | Swap a suffix; replace the first match |
${VAR:-default}, ${VAR:?message} | Use a default; stop with an error if unset or empty |
In a script, put shopt -s extglob on its own line before any !(...) pattern. Bash parses the whole line before running it, so the same line gives a syntax error.
Zsh differences
| Behaviour | Bash | Zsh |
|---|---|---|
| Default shell on macOS | No (old Bash 3.2 still ships) | Yes, since macOS Catalina |
| Glob with no match | Left as typed | Error no matches found; quote URLs and scp host:*.log |
Recursive **/ | Needs shopt -s globstar | On by default |
| Array indexes | Start at 0 | Start at 1 |
| Key bindings | bind, ~/.inputrc | bindkey; bindkey -e for emacs keys, bindkey -v for vi |
| History expansion, Ctrl+R, job control | As above | Same keys and syntax |
tmux and screen basics
tmux and screen keep sessions running on the server after your SSH connection drops. Every key below follows the prefix: Ctrl+B in tmux, Ctrl+A in screen.
| Action | tmux | screen |
|---|---|---|
| New named session | tmux new -s work | screen -S work |
| List sessions | tmux ls | screen -ls |
| Reattach | tmux attach -t work | screen -r work (-d -r to take it from another terminal) |
| Detach | prefix d | prefix d |
| New window | prefix c | prefix c |
| Next / previous window | prefix n / prefix p | prefix n / prefix p |
| Pick from a list | prefix w | prefix “ |
| Split side by side | prefix % | prefix | (then prefix Tab, prefix c for a shell) |
| Split top and bottom | prefix “ | prefix S |
| Move between panes | prefix arrow keys or prefix o | prefix Tab |
| Zoom a pane | prefix z | — |
| Scroll back / copy mode | prefix [ (q to leave) | prefix [ |
| Kill pane / window | prefix x / prefix & | prefix k |
tmux new -d -s upgrade 'dnf -y upgrade 2>&1 | tee /root/upgrade.log'
tmux attach -t upgrade # watch it; prefix d to leave it running
Terminal apps: macOS, iTerm2 and Windows Terminal
| Action | macOS Terminal | iTerm2 | Windows Terminal |
|---|---|---|---|
| New tab | Cmd+T | Cmd+T | Ctrl+Shift+T |
| Split pane | Cmd+D | Cmd+D (side by side), Cmd+Shift+D (top and bottom) | Alt+Shift+Plus (right), Alt+Shift+Minus (down) |
| Close pane | Shift+Cmd+D (split) | Cmd+W (Shell > Close) | Ctrl+Shift+W |
| Clear scrollback | Cmd+K | Cmd+K (Edit > Clear Buffer) | Command palette: Clear buffer |
| Find | Cmd+F | Cmd+F | Ctrl+Shift+F |
| Copy / paste | Cmd+C / Cmd+V | Cmd+C / Cmd+V | Ctrl+C (only with a selection) / Ctrl+V, or Ctrl+Shift+C / Ctrl+Shift+V |
| Command palette or quick switcher | — | Cmd+Shift+O (Open Quickly, finds sessions) | Ctrl+Shift+P |
On a Mac, Alt shortcuts such as Alt+B and Alt+. need the Option key to act as Meta. In Terminal, tick Settings > Profiles > Keyboard > Use Option as Meta key. In iTerm2, set Left Option key to Esc+ under Settings > Profiles > Keys. Option-click in macOS Terminal moves the cursor to that point on the command line.
Official documentation (checked 9 October 2026): Bash Reference Manual · GNU Readline User Interface · tmux(1) manual · GNU Screen manual · Apple: Keyboard shortcuts in Terminal on Mac · iTerm2 documentation · Windows Terminal: Panes · Windows Terminal: Actions
Terminal Cheat Sheet at a glance


Related: Linux Commands Cheat Sheet for Server Admins · Git Cheat Sheet: Branches, Undo, Remotes and Deploys · Online Linux Terminal.
Reading a lot of our guides? Go ad-free with srvScripts Pro for $6 a month. It also pays for new guides. Cancel any time.