Can't use exclamation mark (!) in bash?

I’m trying to use the curl command to access a http url with a exclamation mark (!) in its path. e.g:

curl -v "http://example.org/!287s87asdjh2/somepath/someresource"

the console replies with bash: ... event not found.

What is going on here? and what would be the proper syntax to escape the exclamation mark?

Asked By: netbrain

||

The exclamation mark is part of history expansion in bash. To use it you need it enclosed in single quotes (eg: 'http://example.org/!132').

You might try to directly escape it with a backslash () before the character (eg: "http://example.org/!132"). However, even though a backslash before the exclamation mark does prevent history expansion, the backslash is not removed on some shells in such a case. So it’s better to use single quotes, so you’re not passing a literal backslash to curl as part of the URL.

Answered By: Daniel Pittman

As well as the answer given by Daniel, you can also simply turn off history expansion altogether if you don’t use it with:

set +H

or

set +o histexpand

(the latter also working in zsh, where histexpand is an alternative name for the banghist option for bash compatibility).

In (t)csh where history expansion originates, you’d disable it by assigning the empty string to the $histchars variable with:

set histchars = ''

Or:

set histchars

(not via unset histchars)

That also works in bash and zsh, the two shells that copied that feature, though the syntax is:

histchars=

There.

Beware that bash (contrary to (t)csh or zsh) does not ignore a $histchars variable found in the environment, so beware of the possible consequences if you export that variable.

Answered By: Chris Down

I would personally do single quotes, but for completeness, I will also note since it is a URL, you can encode the ! as %21, e.g. curl -v http://example.org/%21132 .

Answered By: Aaron D. Marasco

I have come across the same problem, and my simple solution was to use a variable:

E=!  
curl -v "http://example.org/${E}287s87asdjh2/somepath/someresource"

Here the simplicity is that (1) It is portable across shells and commands (2) Does not require knowing escape syntax and ASCII codes.

Answered By: Prem

This also can do

curl -v "http://example.org/"'!'"287s87asdjh2/somepath/someresource"
or
curl -v "http://example.org/"!"287s87asdjh2/somepath/someresource"

Which works because bash concatenates adjacent strings. This approach is particularly useful when you have other things that need shell expansion, so you can’t use single quotes for the entire string:

curl -v 'http://example.org/!'"287s87asdjh2/${basepath}/someresource"

! character is used for history expansions in command line prompt.
so this can be a problem in prompt but not in shell script files.
as you can see history expansions work even in double quotes.

Answered By: mug896

Ever since Bash 4.3, you can now use double quotes to quote the history expansion character (edit: as long as the the exclamation mark is at the end of the string or followed by a space)

$ $SHELL --version
GNU bash, version 4.3...
[...]
$ echo "Hello World!"
Hello World!
$ echo "Hello! World"
Hello! World
$ echo "Hello!World"
bash: !World: event not found
$ echo 'Hello!World'
Hello!World
Answered By: Flimm

To those who are using git bash in windows, the accepted answer from @DanielPittman works. However, you should replace the backslash () with a forward slash (/).

For example, in unix, it’d look something like this:

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS!ZR412543s'

For windows, it’d be something like this (focus on the forward slash in the authorization header part)

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS/!ZR412543s'

Answered By: SamuelDev
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.