The more you learn about the linux shell, the more you love it. Reason I am saying this because I recently saw this:
This made me immediately google it and I found an excellent reference here. This is a quick summary of the source:
$ !! # Repeat last command
$ !x # Repeat last command that started with x
$ !?x # Repeat last command that has the substring x
$ !10 # Repeat 10th command in the history file
$ !-10 # Repeat 10th from last command in the history file
$ !!* # Fetch parameters from last command
$ !!^ # Fetch first parameter from last command
$ !!$ # Fetch last parameter from last command
$ !!3 # Fetch third parameter from last command
$ !!:s/foo/bar/ # Repeat last command substituting foo for bar
If you append :p
to any of the above commands then it will only print the command than running it
Infinite Bang Bang
Now what if the last command also contains a !!
. Would it become recursive ? Let’s see:
# : is noop operator. This command sets up our base.
# Note that the !! inside single quote doesn't expand to the previous command
$ : '!!'
# Let's start our recursive operation in here. This is the first sequence in the chain
# Only the !! inside double quotes expands to the previous command - : '!!'
$ : "!!" '!!'
: ": '!!'" '!!'
# Pressing up arrow, we have a second sequence
# Once again, only !! inside double quotes expands and !! appears 3 times after expansion
$ : ": '!!'" '!!'
: ": ': ": '!!'" '!!''" '!!'
# Now, third sequence - !! appears 5 times
$ : ": ': ": '!!'" '!!''" '!!'
: ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'
# Fourth Sequence - !! appears 17 times
$ : ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'
: ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''''" '!!'
# Fifth
$ : ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!'''" ': ": ': ": '!!'" ': ": ': ": '!!'" '!!''" '!!'''" '!!''''" '!!'
: ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": ': ": ': ": '!!'" ': ": ': ": ': ": '
... # !! appears 161 times
In the sixth sequence !!
appears 15681 times and in the seventh, more than 150 million times. Do not even try to run it for the 7th iteration unless you want to end up with a 2GB history file and your shell stuck for hours at 100% CPU.
The 8th sequence has more than 16 Quadrillion bang bangs
Now, I haven’t been able to figure out the exact equation yet for the number of !!
in nth sequence, but this is what happens:
- Any
!!
not surrounded by any quotes is expanded to the previous command !!
surrounded only by single quotes'!!'
do not expand!!
surrounded by double quotes at the outermost level are expanded, even if that bang bang is nested inside single quotes. For e.g." '!!' "
The approximate equation is like this:
f(n) ~ f(n-1)*f(n-1)/2 + f(n-1)/2
Let me know if you can figure out the exact equation. The above commands have been tested on sh and bash.
Update: Thanks to Volker, we have code to calculate the exact number of bang bangs in nth sequence, here, which works till the 7th sequence.
Volker has even submitted the Bang Bang Numbers at OEIS and the sequence has been accepted. View it over here
Update2: Robin Houston wrote an analysis of these numbers on his blog. He also wrote this code for generating the numbers in the Bang Bang Numbers series:
# /usr/bin/env python
p, q = 2, 4
for i in range(4, 16):
print "%d: %d" % (i, 4*p + 2*q + 1)
p,q = 3*p*p + 2*p + p*q, 2*q + 2*p*p + 2*p*q