How to echo a bang!

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.


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 \#\!/bin/bash
#!/bin/bash

Though beware that inside double quotes, the \ is not removed:

$ echo "\!"
\!

! starts a history substitution (an “event” is a line in the command history); for example !ls expands to the last command line containing ls, and !?foo expands to the last command line 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.