wes
wes

Reputation: 1587

Python's subprocess.Popen() results differ from command line?

Using Cygwin on Windows 7 x32, in a VS solution directory, the find command produces correct results:

$ find . -iname "*.sln"
./ProjName.sln

but the same command with Python's subprocess.Popen() seems to be matching on * alone:

>>> import subprocess
>>> print subprocess.Popen(['find', '.', '-iname', '"*.sln"'],
...     stdout=subprocess.PIPE, shell=True).communicate()[0]
.
./.git
./.git/COMMIT_EDITMSG
./.git/config
./.git/description
<snip>

What's wrong with myPopen() call?

Upvotes: 1

Views: 1630

Answers (3)

Weeble
Weeble

Reputation: 17960

On POSIX systems, when you use Popen(['find', '.', '-iname', '"*.sln"'], shell=True), Python does this:

/bin/sh -c find . -iname "*.sln"

If you read the documentation for sh, you'll find that only the first argument after -c is treated as a command string to be executed as a shell script. The remaining arguments are actually treated as arguments to the shell script. In this case, as the shell script consists solely of the command-name "find", the arguments are ignored. You can observe this behaviour if you run:

>>> subprocess.call(['echo arg0 = $0, arg1 = $1', 'foo', 'bar'], shell=True)
arg0 = foo, arg1 = bar
0

Upvotes: 2

NPE
NPE

Reputation: 500913

The following works for me:

>>> import subprocess
>>> print subprocess.Popen(['find', '.', '-iname', '*.sln'],
...     stdout=subprocess.PIPE, shell=False).communicate()[0]

Note the removal of double quotes around *.sln and the setting of shell to False.

This makes sure that the *.sln is passed to find verbatim and is not expanded by the shell.

edit: The following also works:

>>> print subprocess.Popen(['find . -iname "*.sln"'],
...     stdout=subprocess.PIPE, shell=True).communicate()[0]

Upvotes: 3

ciphor
ciphor

Reputation: 8288

The code should be:

print subprocess.Popen(['find . -iname "*.sln"'], stdout=subprocess.PIPE, shell=True).communicate()[0]

Upvotes: 0

Related Questions