15 Linux Bash History Expansion Examples You Should Know

by Ramesh Natarajan on August 8, 2011

Bash history is very powerful. Understanding how to effectively use the bash history expansions will make you extremely productive on the Linux command line.

This article explains 15 examples that uses the following bash history expansion features:

  • Event designators – Refers to a particular command in the history. It starts with a !
  • Word designators – Refers to a particular word of a history entry. Typically this gets combined with an even designator. Even designators and word designators are separated by a colon
  • Modifiers – Modifies the result of the substitution done by the event or word designators

This article is part of our on-going Bash Tutorial Series.

As you already know, to view all the history entries, use the history command. This will display all the commands that were executed earlier along with the number for that command in the history table.

$ history
1 tar cvf etc.tar /etc/
2 cp /etc/passwd /backup
3 ps -ef | grep http
4 service sshd restart
5 /usr/local/apache2/bin/apachectl restart

Bash History Event Designators

1. Execute a specific command from the history using !n

If you’ve executed a command earlier, instead of re-typing it again, you can quickly execute it by using the corresponding number of the command in the history.

For example, to execute command #4, do the following. This will display command #4 from the history, and execute it immediately.

$ !4
service sshd restart

To execute a command that was typed 2 commands back, do the following.

$ !-2

To execute the previous command, do any one of the following:

$ !!

$ !-1

You can also press <Ctrl>-P (if you are in the default emacs mode) to get to the previous command.

If you’ve enabled vi style editing for the command line using ‘set -o vi’, use <Esc>-k to get to the previous command.

2. Execute a command with keywords using !string and !?string

You can also use keywords to execute a command from the history.

The following example will search for previous command that STARTS with the keyword “ps” and execute it. In this example, it picks up the previous command “ps -ef | grep http” and executes it.

$ !ps
ps -ef | grep http

The following example will search for previous command that CONTAINS the keyword “apache” and execute it. In this example, it picks up the previous command “/usr/local/apache2/bin/apachectl restart” and executes it.

$ !?apache
/usr/local/apache2/bin/apachectl restart

3. Replace a string from the previous command using ^str1^str2^

In the following example, first we executed the ls command to verify a file. Later we realized that we want to view the content of the file. Instead of typing the whole file name again, we can just replace the “ls” in the previous command with “cat” as shown below.

$ ls /etc/cron.daily/logrotate

$ ^ls^cat^
cat /etc/cron.daily/logrotate

Note: For additional bash history tips, refer to 15 Examples To Master Linux Command Line History. This explains how to display timestamp in the history, and how to use various history related environment variables including HISTTIMEFORMAT, HISTSIZE, HISTFILE, HISTCONTROL, and HISTIGNORE

Bash History Word Designators

Word designators are very helpful when you want to type a new command, but use the argument from one of the command that was executed earlier. Some of the examples are shown below.

4. Get the 1st argument of a command using :^

In the following example, “!cp:^” was given as an argument to “ls -l” command. “!cp:^” locates the previous command in the history that starts with “cp” and gets the 1st argument of that command.

$ cp /etc/passwd /backup

$ ls -l !cp:^
ls -l /etc/passwd

The following example gets the 1st argument from the previous command.

$ ls -l !!:^

5. Get the last argument of a command using :$

In the following example, “!cp:$” was given as an argument to “ls -l” command. “!cp:$” locates the previous command in the history that starts with “cp” and gets the last argument of that command.

$ cp /etc/passwd /backup

$ ls -l !cp:$
ls -l /backup

The following example gets the last argument from the previous command.

$ls -l !!:$

6. Get the nth argument of a command using :n

In the following example, “!tar:2″ was given as an argument to “ls -l” command. “!tar:2″ locates the previous command in the history that starts with “tar” and gets the 2nd argument of that command.

$ tar cvfz /backup/home-dir-backup.tar.gz /home

$ ls -l !tar:2
ls -l /backup/home-dir-backup.tar.gz

7. Get all the arguments from a command using :*

In the following example, “!cp:*” was given as an argument to “ls -l” command. “!cp:*” locates the previous command in the history that starts with “cp” and gets all it’s arguments.

$ cp /etc/passwd /backup

$ ls -l !cp:*
ls -l /etc/passwd /backup

8. Refer to the recently searched word using !%

As we explained above, the “!?apache” will search for the previous history command that CONTAINS the keyword “apache” and execute it.

$ /usr/local/apache2/bin/apachectl restart

$ !?apache
/usr/local/apache2/bin/apachectl restart

!% will refer to the whole word that was matched by the previous “?” search.

For example, If you’ve searched previously “?apache”, the “!%” will match the whole word “/usr/local/apache2/bin/apachectl”. Note that “/” is treated as part of one word in this context.

So, in this case, by executing the following, you can stop the apache.

$ !% stop
/usr/local/apache2/bin/apachectl stop

9. Get range of arguments from a command using x-y

In the following example, “!tar:3-5″ was given as an argument to “ls -l” command. “!tar:3-5″ locates the previous command in the history that starts with “tar” and gets the arguments from 3 through 5.

$ tar cvf home-dir.tar john jason ramesh rita

$ ls -l !tar:3-5
ls -l john jason ramesh

The following gets all the arguments from 2.

$ ls -l !tar:2-$

Please note the following:

  • !!:* Gets all the arguments from the previous command
  • !!:2* Gets all the arguments starting from 2nd argument.
  • !!:2-$ Same as above. Gets all the arguments starting from 2nd argument.
  • !!:2- Gets all the arguments starting from 2nd argument (except the last argument).

Bash History Modifers

Modifers are given after the word designators, as explained in the examples below.

10. Remove the trailing path name from a word using :h

In the following example, “!!:$:h” takes the last argument of the previous command, and removes the trailing path name. In this case, it removes the filename, and gets only the full path.

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:h
ls -l /very/long/path/name

11. Remove all leading path name from a word using :t

This is exact opposite of the previous example.

In the following example, “!!:$:t” takes the last argument of the previous command, and removes all the leading path names. In this case, it gets only the file name.

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:t
ls -l file-name.txt

12. Remove the file name extension from a word using :r

In the following example, “!!:$:r” takes the last argument of the previous command, and removes only the “.suffix” (which is file name extension here). In this case, it removed .txt

$ ls -l /very/long/path/name/file-name.txt

$ ls -l !!:$:r
ls -l /very/long/path/name/file-name

13. Sed like Substitution in bash history using :s/str1/str2/

Instead of using the “^original^replacement^” as we discussed earlier, we can also use a sed like substitution in the bash history as shown in the example below. This might be easy to remember. !! is to call previous command, “:s/original-string/replacement-string/” is the sed-like syntax to replace a string.

$ !!:s/ls -l/cat/

You can also use the g flag (along with s flag) to do global substitution as shown below. This is helpful when you’ve mistyped multiple word and would like to change all of them together and execute the command again.

In the following example, by mistake I’ve given “password” twice (instead of passwd).

$ cp /etc/password /backup/password.bak

To fix this, just do the following global history sed like substitution.

$ !!:gs/password/passwd/
cp /etc/passwd /backup/passwd.bak

14. Repeat the substitution quickly using :&

If you’ve already executed a bash history substitution successfuly as shown above, you can repeat the same substitution quickly again using :&.

I’ve by mistake typed “password” again instead of “passwd” in another command.

$ tar cvf password.tar /etc/password

Now, instead of retyping the command, or doing the “gs/password/passwd”, I can just use “:&”, which will reuse the last substitution. Use “:g&” for reusing the last subsitution by globally.

$ !!:g&
tar cvf passwd.tar /etc/passwd

15. Print the command without executing it using :p

This is very helpful when you are doing complex history substitution, and you want to view the final command before executing it.

In the following example, “!tar:3-:p”, doesn’t really execute the command.

Since we’ve given “:p” here, it just does the substitution and displays the new command. Once you’ve verified the bash history expansion, and if you think this is the command you intended to run, remove the “:p” and execute it again.

$ tar cvf home-dir.tar john jason ramesh rita

$ tar cvfz new-file.tar !tar:3-:p
tar cvfz new-file.tar john jason ramesh

Linux Sysadmin Course Linux provides several powerful administrative tools and utilities which will help you to manage your systems effectively. If you don’t know what these tools are and how to use them, you could be spending lot of time trying to perform even the basic administrative tasks. The focus of this course is to help you understand system administration tools, which will help you to become an effective Linux system administrator.
Get the Linux Sysadmin Course Now!

If you enjoyed this article, you might also like..

  1. 50 Linux Sysadmin Tutorials
  2. 50 Most Frequently Used Linux Commands (With Examples)
  3. Top 25 Best Linux Performance Monitoring and Debugging Tools
  4. Mommy, I found it! – 15 Practical Linux Find Command Examples
  5. Linux 101 Hacks 2nd Edition eBook Linux 101 Hacks Book

Bash 101 Hacks Book Sed and Awk 101 Hacks Book Nagios Core 3 Book Vim 101 Hacks Book

{ 19 comments… read them below or add one }

1 jalal hajigholamali August 8, 2011 at 3:00 am

Hi,

Very beautiful and usable material

2 Kirti Ranjan Nayak August 8, 2011 at 3:32 am

awesome info. thanks for brushing our knowledge

3 paul August 8, 2011 at 5:09 am

i want to log every command run with any user in /var/log/message.
is that possible

4 gosh August 8, 2011 at 7:15 am

See the 5th point: Get the last argument of a command using :$

$ cp /etc/passwd /backup

$ ls -l !cp:^ —-> it should: ls -l !cp:$ to get the last argument
ls -l /backup

5 Rod Elias August 8, 2011 at 8:28 am

Hi there!
Thanks a ton for sharing such great tips.
Bash is so powerful and those tips are really going to help us a lot.
Cheers!

6 Navin Pathak August 9, 2011 at 6:00 am

Good Afternoon Sir,

This article is very fine I am new with linux Plz publish article based on server related as mail server and ftp,squid etc.

Again thanks for Nice Article

Regards
Navin Pathak

7 Júlio Hoffimann Mendes August 9, 2011 at 6:42 am

Hi Ramesh,

I can’t believe! Your tips are the best! Thank you for turning our console life so much joyful.

Regards,
Júlio.

8 Kundan August 9, 2011 at 7:28 am

Very nice tips
nicely explained

Thanks for sharing

9 bmfx August 9, 2011 at 3:19 pm

Thanks so much :D , nice tips. Thanks for sharing.

10 filterfish August 10, 2011 at 5:36 am

Oh you could just vi bindings on the command and save yourself all that pain.

11 Steffen August 10, 2011 at 12:37 pm

awesome, thanks a lot!

12 Federico August 11, 2011 at 8:33 am

thank you!

in the daily usage of bash i tend to forget some of the features I use less!
I also learned some new tricks from your post!

great stuff!

13 ali August 11, 2011 at 11:54 am

great tutorial Thanks

14 Anonymous August 11, 2011 at 11:53 pm

@paul
Have a look at the script command. (man script)
I would not log this to /var/log/messages, use separate files.

15 Julien August 12, 2011 at 3:31 am

Thanks for sharing, will have hard time to remember all of those thought

16 Frank Han September 5, 2011 at 11:49 am

$ls -l !$

works as same as

$ls -l !!:$

Awesome tips, thank you.

17 Alan Aversa October 26, 2011 at 3:25 pm

Man, I wish I learned all the word designators a long time ago! Thank you!

18 Michael Bates October 29, 2011 at 1:39 pm

Personally, I’m afraid to use some of these designators. It looks too easy to make an error and execute something I didn’t intend. But I guess point number #15 (Print the command without executing it using) addresses that.

19 Curtis November 3, 2011 at 10:03 pm

Don’t forget bash reverse history search ([CTRL]+[R] and enter string, keep pressing [CTRL]+[R] to scroll back) – it’s a bit more safe!

There’s also the [ALT]+[.] shortcut for the last argument. Keep pressing this combination to scroll back :)

Leave a Comment

Previous post:

Next post: