Reputation: 68097
Consider for example the following Python code:
subprocess.call([r'.\tst.bat', '"1|2"'])
Here I've put double quotes around the argument to tst.bat, in order to protect '|' from the shell since tst.bat will ultimately be run via the Windows shell. However, if there are double quotes in arguments, subprocess in Python 2.7 escapes them. The result is that tst.bat receives this argument: \"1|2\".
How can I escape the argument "1|2" so that it's passed untransformed to tst.bat?
Upvotes: 3
Views: 492
Reputation: 42465
Subprocess module on Windows in case of a list of arguments given to the call
method transforms this list into a string using list2cmdline
function. In the docstring of this function one can read:
3) A double quotation mark preceded by a backslash is interpreted as a literal double quotation mark.
According to this the solution of your problem should look like this
subprocess.call([r'.\tst.bat', r'\"1|2\"'])
However it seems like there's a mismatch between documentation and implementation of list2cmdline
function;
Python 2.7.4 (default, Apr 6 2013, 19:55:15) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> print subprocess.list2cmdline([r'\"1|2\"'])
\\\"1|2\\\"
The same behavior is in Python 3.3.1. I raised a bug at http://bugs.python.org/issue18649
UPDATE
It turns out I was confused by very misleading docstring of list2cmdline
function - see http://bugs.python.org/issue18649 for details.
The sequence of arguments passed to subprocess.call
is translated by list2cmdline
function which is concerned only with the quoting mechanism used by MS C runtime and not by quoting mechanism used by cmd.exe. This makes passing arguments - which are later to be interpreted by cmd.exe - to subprocess.call
as a list either very awkward or impossible.
There's one more chance to get it working in this case, though. list2cmdline
double quotes every argument with a space or tab inside. If having a space at the end of your argument does not break the batch file you can add it at the end forcing double quoting as you wanted.
>>> import subprocess
>>> print subprocess.list2cmdline(['1|2 '])
"1|2 "
Upvotes: 1
Reputation: 360495
This (or a similar problem) has been reported as a bug.
References:
Upvotes: 0