Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python subprocess to Bash: curly braces

Tags:

python

bash

popen

I have the following Python lines:

import subprocess
subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0]

Unfortunately, bash completely ignores the --exclude=*{.git,.svn}* flag.

I've narrowed down the problem to the curly braces. --exclude=*.git* will work through python's popen, but the moment curly braces are introduced, I'm left helpless. Any suggestions?

Note: I tried running the command using Python's command library, it produces the exact same output -- and the exact same ignored --exclude flag.

like image 825
user1115304 Avatar asked Dec 25 '11 12:12

user1115304


2 Answers

When you pass shell=True, python translates the command to /bin/sh -c <command> (as described here). /bin/sh apparently does not support the curly braces expansion. You can try the following instead:

import subprocess
subprocess.Popen(["/bin/bash", "-c", "egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory"], stdout=subprocess.PIPE).communicate()[0]
like image 154
Rob Wouters Avatar answered Nov 13 '22 11:11

Rob Wouters


I would guess that it might be shell escaping?

It might be best to do your own splitting up of the arguments, and avoid the shell entirely?

import subprocess
subprocess.Popen(["egrep","-r","--exclude=*{.git,.svn}*","text","~/directory"], stdout=subprocess.PIPE).communicate()[0]

NB: You might have to expand ~, I'm not sure.

Or if bash is supposed to be expanding the braces then you could do it in python:

excludes = ['.git','.svn']
command = ['egrep','-r']
for e in excludes:
    command.append('--exclude=*%s*'%e)
command += ["text","~/directory"]
subprocess.Popen(command, stdout=subprocess.PIPE).communicate()[0]
like image 44
Douglas Leeder Avatar answered Nov 13 '22 13:11

Douglas Leeder