ActiveState Powered by ActiveState

Recipe 498202: Quote python strings for safe use in POSIX shells


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

Comments

  1. 1. At 1:03 a.m. on 19 oct 2006, Rafal Sniezynski said:

    Isn't the quoting of subprocess.list2cmdline safe enough?

  2. 2. At 3:42 a.m. on 19 oct 2006, Richard Philips (the author) said:

    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.

  3. 3. At 7:48 a.m. on 9 nov 2006, Matthew Towler said:

    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.

    def quote_for_POSIX(string):
    
        output = "'"
        output += string.replace( "'", r"\'" )
        output += "'"
    
        return output
    

    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.

  4. 4. At 5:26 p.m. on 10 jan 2007, Steve Freitas said:

    Unnecessary import. The re module isn't actually used in the code, so the import of it can be omitted.

  5. 5. At 2:09 p.m. on 21 feb 2007, Daryl Spitzer said:

    replace() vs. split() and join()? Are split() and join() more efficient than something like:

    return "'%s'" % string.replace( "'", r"'\''" )
    

    or

    return "'" + string.replace( "'", r"'\''" ) + "'"
    

    ?

  6. 6. At 11:36 p.m. on 23 oct 2007, Damon Kohler said:

    repr works well too. Python does some nice escaping on its own in this case. This works well for me:

    msg = "keep's it simple."
    os.system('echo %r' % msg)
    

Sign in to comment