Bash has several built-in special variables. Although most are used only for scripting, there are several that are useful at the command line.
The two I will address in this post are
!! and
!$.
Repeat entire last line: !!
One of the useful parts of bash is its history system. You can see a history of your commands by typing
history at the command prompt. The history command is considered a built-in command because it is not a binary that exists on the filesystem such as
ls or
uptime. The
cd command is another example of a bash built-in.
Built-in bash commands will be covered in more detail in the future, as will the history command. For now, however, know that you can repeat history commands by typing "!" followed by the history ID.
Take the following example:
Listing 1:
dranok@Neptune:~> history
1 which uptime
2 cd /tmp
3 ls -l
4 uptime |
The
which command will tell you the full path of a program, assuming it is in a path specified by your $PATH environment variable. If I wanted to run the
which uptime command again, instead of typing it out I could instead type
!1:
Listing 2:
dranok@Neptune:~> !1
which uptime
/usr/bin/uptime |
!1 gets expanded to the actual command
which uptime. Note
!1 doesn't get saved in your history--if you type history again you'll see the expanded
which uptime command. Likewise if you press the up key you'll see the expanded version there as well.
Also note that when you use special bash variables the expanded command is printed on the subsequent line. This is helpful in figuring out exactly what the bash shell actually ran.
So how does this relate to
!!?
!! is the bash built-in for the last command in your history file--the last command you ran.
Listing 3:
dranok@Neptune:~> cat /tmp/happy
I'm happy!
dranok@Neptune:~> !!
cat /tmp/happy
I'm happy! |
This is very useful in conjunction with the
sudo command, among other things. For example you might run a command as a non-privileged only to discover you need root access. Running
sudo !! is a fast way to achieve this.
Listing 4:
dranok@Neptune:~> cat /tmp/rootonly.txt
cat: /tmp/rootonly.txt: Permission denied
dranok@Neptune:~> sudo !!
sudo cat /tmp/rootonly.txt
This file can only be read by root. |
Repeat last argument: !$
!$ is similar to
!!, however instead of expanding to the entire last command it expands to the last argument of the last command. This is best illustrated by example.
Listing 5:
dranok@Neptune:~> cd /tmp/testdir
-bash: cd: /tmp/testdir: No such file or directory
dranok@Neptune:~> mkdir !$
mkdir /tmp/testdir |
In this case we tried to cd into a directory which did not exist. Since the last argument of the preceding command was
/tmp/testdir, running
mkdir !$ is the equivalent of
mkdir /tmp/testdir
Bash contains many other special variables like
!! and
!$, however these are two of the most ubiquitous and useful.