12

Today, I was caught redhanded while attempting to code golf a password generator for Twitter.

import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))

90 chars. Since that is a lot of spare space, I decided to raise the bar and make it executable too.

echo -e "#!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg

139 chars. Nice, except obviously bash chokes on the exclamation point.

badp@delta:~$ echo -e "#!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg
bash: !/usr/bin/python\nimport: event not found

Pesky exclamation point. "Let's escape it," I thought! I do have one spare character after all.

echo -e "#\!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg

Obviously...

badp@delta:~$ echo -e "#\!/usr/bin/python\nimport string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))">pg;chmod +x pg;./pg
./pg: line 2: syntax error near unexpected token `('
./pg: line 2: `import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))'
badp@delta:~$ cat pg
#\!/usr/bin/python
import string as s,random;print ''.join(random.sample(s.letters+s.digits+s.punctuation,9))

Leaving my asinine code golfing aside -- I can't explain this.

With \!, the exclamation point was escaped, except it really wasn't, because the \! was left as-is for echo to pick up.

One solution could have been using \x21 instead, but I'm not convinced that's the proper way of escaping an exclamation point in a bash command.

tl;dr: How do you properly escape an exclamation point in a bash command?

2
  • Does anyone actually use the !event syntax in the first place? It's always caused me only trouble.
    – badp
    Dec 18, 2010 at 0:12
  • I use it almost daily, (for most of the past 20 years.) !:0 !$ and !^ save so much time and typing. Mar 25, 2020 at 12:29

2 Answers 2

7

Use single quotes:

echo -e '#!/usr/bin/python\nimport string as s,random;print "".join(random.sample(s.letters+s.digits+s.punctuation,9))'>pg;chmod +x pg;./pg

The rules for ! were sort of grafted onto the other quoting rules afterwards (from csh). They were very useful back when shells didn't have command line editing, but some people still use them now.

P.S. Since you're coding for bash:

echo $'#!/usr/bin/python\nimport string as s,random;print"".join(random.sample(s.letters+s.digits+s.punctuation,9))'>pg;chmod +x pg;./pg

This works on most unices:

echo python -c \''import string as s,random;print"".join(random.sample(s.letters+s.digits+s.punctuation,9))'\'>pg;chmod +x pg;./pg

(Not that I understand why you want to create a script or why the script name has to be two letters.)

6
  • Didn't know about $''. :) PS: It was to try and use up those spare characters. I have a feeling of waste when I post tweets shorter than 140 characters.
    – badp
    Dec 18, 2010 at 0:45
  • @badp: So try to make it generate memorable passwords. (As in pwgen vs. pwgen -s.) Dec 18, 2010 at 0:47
  • Might as well use dadadodo for memorable but nonsensical passphrases then :)
    – badp
    Dec 18, 2010 at 0:50
  • Is it not possible to escape exclamation marks when using double quotes? With curl, even \x21 or %21 does not send an exclamation mark in POST parameters.
    – baptx
    Apr 11, 2021 at 16:18
  • 1
    @baptx No, if history expansion is enabled then \! and '!' expand to ! but "\!" expands to \! and "!…" triggers history expansion. Apr 11, 2021 at 18:48
2

I should have Googled before I asked.

Since you do not depend on bash to expand variables [..] you could use single quotes instead. Strings in single quotes are not expanded by bash.

honk in reply to How do I escape an exclamation mark?

1
  • 1
    I'm not marking this answer as accepted, though, because it answers only this specific case. Generally, you can't get away with no expansion.
    – badp
    Dec 18, 2010 at 0:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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