Indradhanush Gupta
Indradhanush Gupta

Reputation: 4237

Why can't I echo "!" in bash?

I tried the following just now:

echo "Hello World!" > hw.txt

And I got this error:

bash: !": event not found

I tried escaping the ! like this:

echo "Hello World\!" > hw.txt

But hw.txt contains:

Hello World\!

Now I tried:

echo "Hello!World" > hw.txt

and I get this:

bash: !World": event not found

But when I tried this:

echo "Hello ! World" > hw.txt

To my surprise it worked!

So I also tried this: (Note the space at the end.)

echo "Hello World! " > hw.txt

Why does bash treat ! like this, even within quotes? And how does it work with a trailing space? Am I missing something obvious?

Upvotes: 0

Views: 853

Answers (3)

chac
chac

Reputation: 31

The trailing space disables the Bash event designator !.

man bash | less -Ip 'Event Designators'

# An  event designator is a reference to a command line entry in the his-
# tory list.  Unless the reference is absolute, events  are  relative  to
# the current position in the history list.
# 
# !     Start  a  history substitution, except when followed by a blank,
#       newline, carriage return, = or ( (when the extglob shell  option
#       is enabled using the shopt builtin).

Another way to disable the event designator ! is to use:

set +H  # ... or ...
set +o histexpand
help set

Upvotes: 3

Alexander
Alexander

Reputation: 10386

Use single quotes for strings that should not be meddled with:

echo '!'

Use double quotes for strings that can be meddled with:

echo "$PWD"

Upvotes: 3

dogbane
dogbane

Reputation: 274592

This behaviour is specified in the bash man page under the HISTORY EXPANSION section:

History expansions are introduced by the appearance of the history expansion character, which is ! by default. Only backslash (\) and single quotes can quote the history expansion character.

Several characters inhibit history expansion if found immediately following the history expansion character, even if it is unquoted: space, tab, newline, carriage return, and =. If the extglob shell option is enabled, ( will also inhibit expansion.

and:

If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed.

Upvotes: 3

Related Questions