Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I tried to create a script by echo'ing the contents into a file, instead of opening it with a editor

echo -e "#!/bin/bash \n /usr/bin/command args"  > .scripts/command

The output:

bash: !/bin/bash: event not found

I've isolated this strange behavior to the bang.

$ echo !
!  

$ echo "!"
bash: !: event not found

$ echo \#!
#!

$ echo \#!/bin/bash
bash: !/bin/bash: event not found
  • Why is bang causing this?
  • What are these "events" that bash refers to?
  • How do I get past this problem and print "#!/bin/bash" to the screen or my file?
share|improve this question
add comment

4 Answers

up vote 22 down vote accepted

Try using single quotes.

echo -e '#!/bin/bash \n /usr/bin/command args'  > .scripts/command

echo '#!'

echo '#!/bin/bash'

The problem is occurring because bash is searching its history for !/bin/bash. Using single quotes escapes this behaviour.

share|improve this answer
add comment

As Richm said, bash is trying to do a history match. Another way to avoid it is to just escape the bang with a \:

$ echo "\!"
!

$ echo \#\!/bin/bash
#!/bin/bash
share|improve this answer
3  
In bash, "\!" actually expands to \!, not !, supposedly for POSIX compliance. –  Mikel Apr 7 '11 at 23:09
    
@Mikel Sigh. So many differences between zsh and bash –  Michael Mrozek Apr 8 '11 at 3:55
add comment

! starts a history substitution (an “event” is a line in the command history); for example !ls expands to the last command beginning with ls, and !?foo expands to the last command containing foo. You can also extract specific words (e.g. !!:1 refers to the first word of the previous command) and more; see the manual for details.

This feature was invented to quickly recall previous commands in the days when command line edition was primitive. With modern shells (at least bash and zsh) and copy-and-paste, history expansion is not as useful as it used to be — it's still helpful, but you can get by without it.

You can change which character triggers history substitution by setting the histchars variable; if you rarely use history substitution, you can set e.g. histchars='¡^' so that ¡ triggers history expansion instead of !. You can even turn off the feature altogether with set +o histexpand.

share|improve this answer
add comment

The proposed solutions don't work in, e.g., the following example:

$ bash -c "echo 'hello World!'"
-bash: !'": event not found
$

In this case the bang can be printed using its octal ASCII code:

$ bash -c "echo -e 'hello World\0041'"
hello World!
$
share|improve this answer
    
In your first command, the ! is between double quotes, where as other answers indicate it retains its history expansion meaning. You could use bash -c 'echo '\''hello World!'\' or bash -c "echo 'hello World"\!"'". –  Gilles Dec 26 '10 at 11:18
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.