4

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

4 Answers 4

9

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.

3
  • Thanks for answering such a silly question Joel Davis! Cheers
    – Brandon D.
    Commented May 27, 2013 at 21:54
  • 1
    +1 for a great answer. I added an explanation of the two line output of echo !!. It took me a little while to figure it out so I thought I'd point it out. Hope you don't mind.
    – terdon
    Commented May 27, 2013 at 22:28
  • Not a problem, clarity is key.
    – Bratchley
    Commented May 27, 2013 at 22:32
2

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).

1
  • I would hope that the questioner would take this opportunity to get to grips with history expansion, since it's really quite useful..
    – evilsoup
    Commented May 28, 2013 at 4:22
1

You need to escape the bang:

echo -e "Hello\nWorld"\!
Note: Having the bang outside of the quotes is intentional. Otherwise \! is echod.

1
  • 1
    What happens if you remove the backslash...? Commented May 27, 2013 at 21:49
1

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.

2
  • Appreciate the quick feedback sir!
    – Brandon D.
    Commented May 27, 2013 at 21:54
  • 1
    Clarification: the ! 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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .