Why am I not able to use "!" when trying to echo a message in terminal? For example:
echo -e "Hello\nWorld!"
bash returns the following command:
bash !: event not found
The !
character is called "bang" and bash
uses it for recalling command history. You can use it four ways:
!<firstFewCharsOfPreviousCommand>
example:
!rm
That will go to the last command you executed that began with "rm" and execute the whole thing. Be careful when repeating potentially destructive commands like rm, as you may unintentionally execute another one than you thought you would. Above is illustration only, using bash's CTRL-R
reverse search function is a much safer alternative.
!<indexInCommandHistory>
example:
!433
The index is the number that appears next to the command when you run the history
command.
!!
No example necessary as that's all there is to it. It re-executes the immediately previous command (same as up arrow on most Linux distributions).
!$
Example:
# ls -lh /etc/fstab
# vi !$
Another literal, when bash executes this, the !$
is replaced by the last word (string of characters without whitespace)
As you can see with the last one, you can even use it as part of a larger or different command. Another example of that with !!
:
[root@hypervisor libsceptre]# echo hey
hey
[root@hypervisor libsceptre]# echo !!
echo echo hey <-- printed to stderr so you know what !! was expanded to
echo hey
[root@hypervisor libsceptre]#
If you want bash to, for whatever reason, view the character as a literal and not try to interpret it, you put the text in single quotes:
[root@hypervisor libsceptre]# echo -e "Hello\nWorld!"
-bash: !": event not found
[root@hypervisor libsceptre]# echo -e 'Hello\nWorld!'
Hello
World!
[root@hypervisor libsceptre]#
The reason your command isn't working is because it's trying to find the last command you wrote that began with a double quote (the functionality described in my first example) and can't find it.
echo !!
. It took me a little while to figure it out so I thought I'd point it out. Hope you don't mind.
If you don't use history expansion (and you obviously don't) then you should rather disable it than learn the strange quoting and inhibition rules.
set +H
or set +o histexpand
gets you rid of it. You can check whether it is active by echo $-
("H" shows it being active) or set -o
(histexpand
).
You need to escape the bang:
echo -e "Hello\nWorld"\!
Note: Having the bang outside of the quotes is intentional. Otherwise \!
is echod.
The special meaning of !
is still active inside double quotes. !
is a shell keyword that for instance takes an integer n as argument and runs the n'th command in your shell history. Use single quotes or escape the character to avoid confusion.
You can read more about history command expansion in man history
.
!
keyword is something else: it's the POSIX keyword used to negate a pipeline exit status. man history
is unlikely to document bash
's or any shell history command or mechanism (though on some system, it may document the readline
's libhistory API which is similar to bash
's since bash
uses a modified version of readline
). Refer to the bash
manual instead.
Commented
Jun 5, 2013 at 13:26