Search notes:

Bash - history

The commands executed in bash are stored in a history file.

Bash history expansion

Apparently, histexpand (set -o histexpand) must be in effect for history expansion to work.

Using !

The exclamation mark can be used to refer to portions of one of the last commands executed.
!! is expanded to the last command. So
$ !!
repeats the last command.
A useful application for this construct is if sudo was forgotten:
$ pacman -Syu
error: you cannot perform this operation unless you are root.
$ sudo !!
Repeat the most recent command that starts with ls:
$ !ls
Repeat the most recent command that contains foo:
$ !?foo
:p does not execute the command but rather prints it:
$ !ls:p

!^ and !$

!^ is replaced with the first argument:
$ echo foo bar baz
foo bar baz
$ echo abc !^ def
abc foo def
Similarly, !$ is replaced with the last argument.

nth argument

Similar to !^ and !$, the nth argument can be referred to with !!:n:
$ echo one two three
one two three
$ echo !:3 !:2 !:1
three two one
!^ and !!:^ seem to be equivalent, as well as also !$ and !!:$.
All arguments are referred to with !!:*
Arguments n through m are referred to with !!:n-m
Arguments n and following are referred to with !!:n*

Searching for commands

!?text? searches for the last command that contained text and executes it.
Unfortunately, regular expressions seem not possible.

Substituting elements in previous commands

!!s/text/replacement/ substitutes the first occurence of word:
$ !!:s/foo/bar/
gs/text/replacement/ substitutes every occurence of word (g=global).
:& reuses the last substitution:
!ls:&

^text^replacement^

^text^replacement^ replaces text in the last command with replacement.
$ ls -l tmp
$ ^-l^-la^

!n and !-n

As !! refers to the last command, !-n refers to the n-th last command and !n to command with number n (as printed with the history command).
As a convenience, $PS1 can be set to something like export PS1="\!$ " to always print the current history number which can be used in !n.

Modifiers

The modifiers :h, :t, :r and :e can be used to select parts of a directory and/or file path:
#!/bin/sh

echo "PS1=
echo /path/to/a/file.extension
echo !-1:$:h  # head,             expands to /path/to/a
echo !-2:$:t  # tail,             expands to /file.extension
echo !-3:$:r  # remove extension, expands to /path/to/a/file
echo !-4:$:e  # extension only,   expands to .extension
" | bash -i  # Use -i to start interactive shell
Github repository about-Bash, path: /history/modifiers
See also vim's fnamemodify.

See also

Environment variables

HISTCONTROL

When set to ignorespace (or ignoreboth), command lines starting with a space won't go to the history file.

HISTIGNORE

HISTIGNORE is a colon-delimited list of (non regexp?) patterns that should be ignored in the history file.
The & is a special pattern to supress duplicate entries.

histappend

By default, bash overwrites the history when the session ends. With setting histappend (shopt -s histappend), bash appends the commands executed during a session when it ends.

See also

fc is a bash built-in that allows to edit commands stored in the history with an editor.

Index