Understanding the exclamation mark (!) in bash

I used

history | less

to get the lines of previous commands and from the numbers on the left hand side I found the line I wanted repeated (eg. 22) and did

!22

at the command prompt and it worked — executing the set of commands on the line I did at that time. I cannot figure out where the exclamation mark is used, what does it represent in terms of actions taken by bash, and where to use it. From the documentation I do not see an explanation that is ‘tangible’.

Asked By: Vass

||

! invokes history expansion, a feature that originally appeared in the C shell, back in the days before you could count on terminals to have arrow keys. It’s especially useful if you add the current command number to the prompt (PS1="!$ ") so you can quickly look at your screen to get numbers for past commands.

Now that you can use arrow keys and things like Ctrl-R to search the command history, I don’t see much use for the feature.

One variant of it you might still find useful is !!, which re-executes the previous command. On its own, I don’t find !!Enter any faster than just Enter, but it can be helpful when combined into a larger command.

Example: A common pilot error on sudo based systems is to forget the sudo prefix on a command that requires extra privileges. A novice retypes the whole command. The diligent student edits the command from the shell’s command history. The enlightened one types sudo !!.

Processing ! in this way is enabled in Bash by default in interactive shells and can be disabled with set +o histexpand or set +H. You can disable it in Zsh with set -K.

Answered By: Warren Young

If there isn’t a longer answer here there’s certainly one on Super User, since I’ve read one recently. In the bash man page you can find a huge section titled HISTORY EXPANSION on the matter.

You can do a whole host more than just run the last command, or command number X. You can do things like !cat to run the last command that started with cat. Or !?bash?:s/bash/csh/ runs the last command containing bash but replaces it with csh.

Answered By: Cry Havok

A friend of mine emailed me this:

It’s part of GNU history library. In bash it is used to re-run
commands in your history. If you want to be hardcore, grep for
history_expansion_char in bash-4.1/lib/readline/histexpand.c for
implementation details.

Answered By: Vass

A lot more can be done with ! such as:

  • execute a command which is typed before 3 commands: !-3
  • execute a command that starts with !ls

and a lot more. See 15 Linux Bash History Expansion Examples You Should Know

Answered By: user379997

Of course you can do !! to reuse the last command in bash shell. And then there is !$ to reuse the last part of your last command.

e.g. view some file

less path/to/your/file.txt

If you now want to edit the same file, you can use !$ to get only the file path from the last command

vim !$

EDIT:

You can use all the arguments of the previous command with !*

e.g.: This will create some files and remove all of them

$ touch a.txt b.txt c.txt d.txt
$ rm !*

Again , you can use a specific argument of the previous command

e.g. This creates 4 files and will remove the 3rd file (c.txt)

$ touch a.txt b.txt c.txt d.txt
$ rm !:3

Similarly, you can use a range of arguments from the last command as follows

$ touch a.txt b.txt c.txt d.txt
$ rm !:2-4

This will reuse arguments 2 to 4 which evaluates the expression to rm b.txt c.txt d.txt

Answered By: Teshan Shanuka J
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.