tags:

views:

280

answers:

3

Hi Folks,

Is there a python module that will properly parse/unparse strings for using in shell commands? I'm looking for the python analog to perl's String::ShellQuote::shell_quote:

$ print String::ShellQuote::shell_quote("hello", "stack", "overflow's", "quite", "cool")
hello stack 'overflow'\''s' quite cool

And, even more importantly, something which will work in the reverse direction (take a string and decompose it into a list).

Thanks!

/YGA

+5  A: 

You should never have to shell quote. The correct way to do a command is to not do shell quoting and instead use subprocess.call or subprocess.Popen, and pass a list of unquoted arguments. This is immune to shell expansion.

i.e.

subprocess.Popen(['echo', '"', '$foo'], shell=False)

If you want to unquote shell quoted data, you can use shlex.shlex like this:

list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))
Jerub
What if I need to pass a command (that requires escaping) for ssh to execute once it reaches the other side?
Mike Boers
This is not a helpful answer (well it answers one half my question, so it's half helpful...). There are are any number of occasions when you need to shell quote -- Mike Boers gives just one great example (in fact, that's the one I'm running into)
YGA
actually even worse, the given example breaks:(Pdb) list(shlex.shlex("hello stack 'overflow'\''s' quite cool"))*** Error in argument: '(shlex.shlex("hello stack \'overflow\'\\\'\'s\' quite cool"))'
YGA
+1  A: 

Looks like

> ipython

# In [1]: 
import pipes

# In [2]: 
pipes.quote("hello stack overflow's quite cool")
# Out[2]: '"hello stack overflow\'s quite cool"'

gets me far enough.

YGA
A: 

I'm pretty sure that pipes.quote is broken, and should not be used, because it does not handle zero-length arguments correctly:

>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

I believe the result should be something like

mycommand arg1 '' arg3
John Wiseman
fair enough. but then we need a better solution :-)
YGA