Often one has to quote a python string so that the result can be used as an argument to a command running in a POSIX shell.
The function QuoteForPOSIX can be used with sh, bash, csh, ksh
Python, 26 lines
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
import re def QuoteForPOSIX(string): '''quote a string so it can be used as an argument in a posix shell According to: http://www.unix.org/single_unix_specification/ 2.2.1 Escape Character (Backslash) A backslash that is not quoted shall preserve the literal value of the following character, with the exception of a <newline>. 2.2.2 Single-Quotes Enclosing characters in single-quotes ( '' ) shall preserve the literal value of each character within the single-quotes. A single-quote cannot occur within single-quotes. ''' return "\\'".join("'" + p + "'" for p in string.split("'")) if __name__ == "__main__": import os filename = "filename with spaces.doc" os.system("ls " + QuoteForPOSIX(filename))
Isn't the quoting of subprocess.list2cmdline safe enough?
Use of list2cmdline. list2cmdline has two 'problems':
(1) It is not mentioned in the Python documentation (a sure sign that the author prefers to keep the use of it private and does not want to take the burden of maintaining it)
(2) From the code, it is clearly for use in a Microsoft only environment. QuoteForPOSIX is intended for UNIX environments.
The subprocess module is a goldmine for little nuggets like list2cmdline and I really hope the author would promote it.
Code does not work. The original code does not run. 'p' is used before the loop that declares it. I belive the following code does the same thing and does work.
As a side issue I have found that if using file names escaped this way as the command line in a call to os.popen() the quoting is not respected and a name with spaces is incorrectly interpreted as multiple arguments.
Unnecessary import. The re module isn't actually used in the code, so the import of it can be omitted.
replace() vs. split() and join()? Are split() and join() more efficient than something like:
repr works well too. Python does some nice escaping on its own in this case. This works well for me:
All the above is wrong since for sh, \' is not valid within single quotes. The "pipes" module available since python 1.6 has a handy function to do the right thing.
Another hack that is not as nice as the pipes.quote() mentioned above is to, allow ' within single quotes by them with '"'"'. I.E. you could quote the string like:
Note that pipes.quote is broken, it does not handle zero-length arguments. That is, pipes.quote('') => '', but it should be something like "''".
The flaw you describe in pipes.quote was fixed in Python 2.6.