# Bash and Zsh ## Keyboard Shortcuts (Bash & Zsh) | macOS | Windows/Linux | Action | |-------|---------------|--------| | `Esc` then `.` or `Opt+.` | `Esc` then `.` or `Alt+.` | Insert last argument from previous command | | `Ctrl+K` | `Ctrl+K` | Cut right (Kill) | | `Ctrl+U` | `Ctrl+U` | Cut left (cUt); in Zsh kills whole line | | `Ctrl+Y` | `Ctrl+Y` | Paste (Yank) | | `Opt+W` | — | Clear line before cursor | | `Ctrl+W` | `Ctrl+W` | Kill word | | `Ctrl+X` then `E` | `Ctrl+X` then `E` | Edit current command in default editor | `reset` — solve strange terminal situations ## History Expansion & Rerun Cheatsheet |**Category**|**Syntax**|**Meaning / Example**| |---|---|---| |**Basic Re-run**|`!!`|Last command| ||`!n`|Command number _n_ from history| ||`!-n`|Command _n_ commands ago| ||`!string`|Last command starting with string| ||`!?string?`|Last command containing string| |**Arguments from Last Command**|`!
|Last argument. `echo foo bar` → `!
= bar| ||`!^`|First argument. `cp foo bar` → `!^` = foo| ||`!*`|All arguments. `cp foo bar` → `!*` = foo bar| ||`!:n`|nth argument (0 = command itself)| ||`!:n-m`|Range of arguments| ||`!:n-
|From nth to last| |**Substitution**|`!!:s/old/new/`|Replace first occurrence| ||`!!:gs/old/new/`|Replace all occurrences| ||`^old^new^`|Shorthand: rerun last command with first old → new| |**Modifiers**|`:p`|Print the expanded command without executing| ||`:h`|Remove last path component (head)| ||`:t`|Keep only last path component (tail)| ||`:r`|Remove file extension (root)| ||`:e`|Keep only file extension| ||`:q`|Quote substituted words| |**Other Tricks**|`!#`|Refers to current line typed so far| ||`fc`|Opens last command in $EDITOR for editing before rerun| |**Combining**|`B && !!`|Run B then rerun last command A| ||`B && !string`|Run B then rerun last command starting with string| ||`history` + `!n`|Run command _n_ again (from history list)| ## Common `!!` Recipes `!!` refers to the previous command and can be reused at will. ```bash sudo !! # Rerun previous command as sudo !! # Rerun previous command !! > output.txt # Save previous command's output to file ``` See [[#Writing Output to File]] for more output redirection options. ## Managing History **Delete a range of history entries (e.g. 100–110):** ```bash for i in {100..110}; do history -d 100; done ``` Always delete from the starting line number repeatedly — each deletion shifts remaining entries up. **Edit history file directly:** ```bash # 1. Open history file nano ~/.bash_history # 2. Delete the lines you want # 3. Save and exit # 4. Reload history history -r ``` ## Job Control [Job Control Documentation](http://web.mit.edu/gnu/doc/html/features_5.html) - `Ctrl+Z` — pause current program and return to shell - `fg` — resume job in foreground - `bg` — run job in background - `jobs` — list all jobs with their job numbers (`%1`, `%2`, ...) **Queue a command after current one:** 1. `Ctrl+Z` to pause current command 2. Optionally `bg` to resume in background 3. `fg && command2` to resume in foreground and queue command2 after success - Use `;` to run command2 regardless of success/failure - Use `||` to run command2 only if command1 fails **Detach process from terminal:** 1. `Ctrl+Z` to pause 2. `bg` to run in background 3. `disown -h [job-spec]` where `[job-spec]` is the job number (like `%1`) so it isn't killed when terminal closes **Start detached from the beginning:** ```bash ./long_running_process options & disown ``` **Sources:** - <https://unix.stackexchange.com/questions/487955/how-to-plan-a-task-to-run-after-another-already-running-task-in-bash> - <https://stackoverflow.com/a/625436/4700312> ## Directory Stack (`cd -`, `pushd`, `popd`) `cd -` switches to the previous directory (stored in `$OLDPWD`). Same principle as [[Git - Miscellaneous#Switch to Previous Branch|git checkout -]] for branches. ```bash cd - # previous directory dirs -v # list the directory stack with indices pushd /some/dir # push current dir onto stack, cd to target popd # pop top of stack, cd back ``` | Feature | Bash | Zsh | |---------|------|-----| | `cd -` (previous dir) | Yes | Yes | | `cd -2`, `cd -3` (nth previous) | No | Yes | | `dirs -v` (list stack) | Yes (manual `pushd` only) | Yes | | Auto directory stack | No | Yes (with `AUTO_PUSHD`) | In zsh, enable `AUTO_PUSHD` so every `cd` populates the stack automatically: ```zsh setopt AUTO_PUSHD # every cd acts like pushd setopt PUSHD_IGNORE_DUPS # skip duplicates ``` Then `cd -2`, `cd -3` etc. just work. With oh-my-zsh, `d` shows the directory stack (top 10) and bare numbers `1`–`9` are aliases for `cd -1` through `cd -9`. Also provides `...`=`../..`, `....`=`../../..`, etc. ## Bypassing Aliases, Functions, and Builtins Three prefixes control how the shell resolves a command name: | Prefix | Skips | Runs | |--------|-------|------| | `\cmd` | aliases | function → builtin → external | | `command cmd` | aliases + functions | builtin → external | | `builtin cmd` | aliases + functions + external | builtin only | ```bash \opencode # skip the alias, run the function/binary command opencode # skip alias AND any function named opencode builtin cd /tmp # guaranteed shell builtin, nothing else ``` `builtin` is needed when a function overrides a builtin — e.g. fzf's `cd` function uses `builtin cd` internally to avoid calling itself. ## Writing Output to File ```bash command > file.txt # overwrite command >> file.txt # append command | tee file.txt # overwrite + display command | tee -a file.txt # append + display ``` **Capture output in a variable:** ```bash last_output=$(your_command) echo "$last_output" > output.txt ``` ## Functions - `declare -F` — list all defined function names - `declare -f` — list all functions with their bodies --- See also: [[Misc CLI]], [[Nohup]], [[Screen]]