Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to printf an exclamation mark in bash? [duplicate]

I need to printf a simple script and redirect the output to a file, but when I do this:

printf "#!/bin/bash\ntouch /tmp/1234567890_$RUN" > /tmp/password-change-script_$RUN.sh

I get this error:

bash: !/bin/bash\ntouch: event not found

If I escape the exclamation mark:

printf "#\!/bin/bash\ntouch /tmp/1234567890_$RUN" > /tmp/password-change-script_$RUN.sh

Then the escape character is still present in the file.

cat /tmp/password-change-script_$RUN.sh
#\!/bin/bash
touch /tmp/1234567890_111

By the way, in this particular case, the #!/bin/bash MUST be in the file. For some reason the binary file that executes the script won't read the file otherwise.

like image 594
David Mulder Avatar asked Feb 21 '13 20:02

David Mulder


People also ask

What does exclamation mark do in bash?

Bash maintains the history of the commands executed in the current session. We can use the exclamation mark (!) to execute specific commands from the history.

How do I escape exclamation mark in bash?

In addition to using single quotes for exclamations, in most shells you can also use a backslash \ to escape it.

How do I type an exclamation point in bash?

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

What does double exclamation mark do in Linux?

It simply prints out the result of the substitution (which is the command it is about to execute) and than the result of the commands execution. @Danagon I think I might have misperceived the question and my answer may not apply, but history expansion still applies here.


1 Answers

The ! character is expanded in double-quoted strings, but not in single-quoted strings.

printf '#!/bin/bash\ntouch /tmp/1234567890_'"$RUN"

It's also not expanded when it appears by itself or at the end of a word; this isn't as clean but:

printf "#%c/bin/bash\ntouch /tmp/1234567890_$RUN" !

You can also temporarily turn off history substitution by (temporarily) setting $histchars to the empty string; this turns off the special treatment of !:

histchars=
printf "#!/bin/bash\ntouch /tmp/1234567890_$RUN"
unset histchars

Or you can execute the printf command in a script rather than interactively (history substitution is on by default only for interactive shells).

like image 180
Keith Thompson Avatar answered Sep 26 '22 17:09

Keith Thompson