Ever forget to issue sudo before a command? Ever had to repeat a whole command because you had a typo? Have you ever thought it would be nice to have shortcuts to repeat your previous commands? If this sounds like you, I have something to share. In this article, I will show you how to use bash bang ( ! ) commands, which make it easy to repeat commands and fix errors.

Command repeat basics

Bash provides access to the list of commands you previously issued, which is known as your command history. The value of the HISTSIZE variable sets the number of commands that are saved in your history list. By default, this value is 500. These previously issued commands (known as your history list) are stored in your history file. Its default location is ~/.bash_history , and this location is stored in the shell variable HISTFILE .

Under the hood, bang (!) commands introduce commands from your bash history list into the input stream. This feature makes it easy to repeat commands, substitute text, manipulate arguments, and fix typos in your previous commands quickly.

Command repeat examples

Here are some examples of what you can do with bash bang.

Repeat the last command matching a string’s beginning

The bang ( ! ) followed by the first character (or string) matching the command you want to run will repeat the most recent instance of that command:

$ ls dir dir1 dir2 file file1 file2 hello.txt $ !l ls dir dir1 dir2 file file1 file2 hello.txt $ !ls ls dir dir1 dir2 file file1 file2 hello.txt

Repeat the last command matching anywhere in a string

The !?<string> format does the same as the above, but <string> doesn’t have to be at the beginning of the command:

$ cat hello.txt Hello world ..! $ !?hello.txt cat hello.txt Hello world ..!

Repeat the nth command from your history

Repeating the nth command from your bash history (counting down from the top) is as simple as using a bang with the number in question:

!10

Repeat the nth command from your last history entry

Repeating the nth command from your bash history (counting up from the bottom) is as simple as using a bang with a minus and the number in question:

!-10

Repeat the last command

If there is one bang command that I use all the time, it would be !! . The bang-bang ( !! ) command repeats the last command from the history list, behaving the same as !-1 :

$ cat hello.txt Hello world ..! $ !! cat hello.txt Hello world ..!

Bang-bang ( !! ) is useful when you need to repeat the previous command, or if you need to prefix sudo , or pipe output:

$ yum update Loaded plugins: priorities, update-motd, upgrade-helper You need to be root to perform this command. $ sudo !! sudo yum update Loaded plugins: priorities, update-motd, upgrade-helper

$ ls dir dir1 dir2 file file1 file2 hello.txt $ !! | grep file ls | grep file file file1 file2 $

Repeat but substitute a string

Often I issue long commands and reissue them with different switches. Or, I need to reissue a command because there was a typo in my previous command. String substitution lets me do this without retyping the whole long command.

There are two ways we can achieve this result. One is by using:

!!:s^<old>^<new>

This structure substitutes a string for the previous command:

$ ls /etc/httpd/conf.d autoindex.conf notrace.conf php.conf php-conf.7.2 README userdir.conf welcome.conf $ !!:s^conf.d^conf ls /etc/httpd/conf httpd.conf magic

You can even do the same with !<string>:s^<old>^<new> :

$ !l:s^conf^conf.d ls /etc/httpd/conf.d autoindex.conf notrace.conf php.conf php-conf.7.2 README userdir.conf welcome.conf

This option is useful when you need to do string substitution for a command that was not the most recent.

The other way we can achieve this result is through the structure ^<old>^<new> . This format substitutes strings for the most recent command, similar to !!:s^<old>^<new> :

$ cd /etc/httpd/conf.d /etc/httpd/conf.d /etc/httpd/conf.d $ ^conf.d^conf cd /etc/httpd/conf /etc/httpd/conf $

Repeat command arguments

Often, we use the same arguments from a preceding command. If you have a long argument, you probably want to repeat it with the next command. Let’s look at some bash bang commands that can do this for us.

First, the format !:n repeats the nth argument from the preceding command, with 0 being the command itself:

~/project $ ls -a -l total 32 drwxrwxr-x 7 user user 4096 Sep 9 20:30 . drwx------ 16 user user 4096 Sep 9 20:10 .. drwxrwxr-x 2 user user 4096 Sep 9 16:02 dir drwxrwxr-x 2 user user 4096 Sep 9 16:02 dir1 drwxrwxr-x 2 user user 4096 Sep 9 16:02 dir2 drwxrwxr-x 2 user user 4096 Sep 9 20:30 dir3 -rw-rw-r-- 1 user user 0 Sep 9 16:02 file -rw-rw-r-- 1 user user 0 Sep 5 16:07 .file -rw-rw-r-- 1 user user 0 Sep 9 16:01 file1 -rw-rw-r-- 1 user user 0 Sep 9 16:01 file2 -rw-rw-r-- 1 user user 16 Sep 9 16:03 hello.txt drwxrwxr-x 2 user user 4096 Sep 5 16:08 .hidden_dir -rw-rw-r-- 1 user user 0 Sep 5 16:08 .hidden_file ~/project $ ls !:1 ls -a . .. dir dir1 dir2 dir3 file .file file1 file2 hello.txt .hidden_dir .hidden_file

Second, !!:$ repeats the last argument from the preceding command. You can shorten this command to !$ and $_ :

project $ mkdir dir3 project $ cd !$ cd dir3 project/dir3 $

You might ask, "What if I want to use this technique with a command I issued previously, but not the most recent one?" You can do so with bang commands, using either:

!<command you've issued previously >:$ $ mkdir -p hello/test1/test2 $ ls !mkdir:$ ls hello/test1/test2

or:

!<command you've issued previously >:n $ ls !mk:2 ls hello/test1/test2

Print out commands

Sometimes you might want to print out the command, but don’t want it executed. You can accomplish this task with !:p :

~/project $ cat hello.txt Hello world ..! ~/project $ !:p cat hello.txt ~/project $

In fact, you can print out any command in your history list without executing it. Just issue one of the following:

$ !<command>:p $ !mkdir:p mkdir -p hello/test1/test2 $ !<string>:p $ !su:p sudo yum check-update $ !mk:p mkdir -p hello/test1/test2

Recall commands with reverse-i-search

As a sysadmin, you probably issue hundreds of commands every day. You might have a hard time recalling some commands or recalling part of one. Here is another option for finding the one you need.

(reverse-i-search)`<search string>’: <output> (reverse-i-search)`yu': sudo yum check-update (reverse-i-search)`cd': cd /etc

CTRL+R activates reverse-i-search , which provides a nice search area, giving you an easier way to navigate through your history.

Conclusion

These are useful bash bang ( ! ) commands that every sysadmin should be familiar with. These commands save tons of time and give you the ability to quickly fix command errors. Read more about bash in its man page, with the command man bash .

[Want to try out Red Hat Enterprise Linux? Download it now for free.]