Is it possible to use the so-called bang-commands (!
+ command/symbol, like e.g. !!
or !$:p
) in bash scripts and in bash aliases?
I wanted to add the line
alias getit='sudo apt-get install !!'
to my ~/.bashrc
file to be able to install a not found command by typing getit
after the non-successful call to the command itself, similar to the behavior of the tool The Fuck, just with less swearing…
However, this line does not work as can be seen in the output below:
$ cowsay
The application »cowsay« is currently not installed.
You can install it by typing:
sudo apt-get install cowsay
$ getit
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package !!
$
Note that I translated the output of the first command myself from German, as LANG=C
did not work on that… For whatever reason.
Anyway, you can see that the bang-command in the alias does not get interpreted to be replaced with the last executed command but stays the same string. I already found out that bang-commands usually only work within the interactive shell and therefore not within scripts.
Can this setting be changed, so that !!
gets interpreted as the last executed command string within scripts? How about aliases, is it possible there?
Best Answer
History expansion is done before alias expansion, so you'll have to use the
history
built-in to perform the expansion yourself:However, the above alias uses the whole last executed command as argument for
sudo apt-get install
, which means if we had given an argument to the failed command (likecowsay "Hello"
), we would now also have this argument appearing in the list of packages to install (sudo apt-get install cowsay "Hello"
).As this is not intended, we should modify the alias as steeldriver suggested and use
!:0
instead of!!
to only get the first word (the command name):We still have to take care that this procedure only works, if the failed command name and its package name are equal. It would e.g. not work for the command
lynx
(a CLI browser), because it is included in the packagelynx-cur
.