Bash的Python子进程:花括号

Bash的Python子进程:花括号,python,bash,popen,Python,Bash,Popen,我有以下Python代码行: import subprocess subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0] 不幸的是,bash完全忽略了--exclude=*{.git、.svn}*标志 我已经把问题缩小到了花括号上--exclude=*.git*将在python的popen中工作,但

我有以下Python代码行:

import subprocess
subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0]
不幸的是,bash完全忽略了--exclude=*{.git、.svn}*标志

我已经把问题缩小到了花括号上--exclude=*.git*将在python的popen中工作,但一旦引入大括号,我就无能为力了。有什么建议吗


注意:我尝试使用Python的命令库运行该命令,它会产生完全相同的输出——以及完全相同的忽略——排除标志。

我猜可能是shell转义

最好是自己拆分参数,并完全避免使用shell

import subprocess
subprocess.Popen(["egrep","-r","--exclude=*{.git,.svn}*","text","~/directory"], stdout=subprocess.PIPE).communicate()[0]
注意:您可能需要展开
~
,我不确定

或者,如果bash应该扩展大括号,那么可以使用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]

当您传递shell=True时,python将命令转换为
/bin/sh-c
(如上所述)/bin/sh显然不支持花括号扩展。您可以尝试以下方法:

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

您需要引用该表达式,以防止在启动时bash根据当前工作目录对其求值。假设您正在查找“文本”(带引号),您的搜索词也有一个bug。您的转义将引号转换到Python字符串中,但需要再次执行才能让shell看到引号


也就是说,
--exclude='*{.git、.svn}*'\\\\\\\\\\“…

从Python Popen的角度来看,如果您在Python变量中捕获输出,您所编写的内容是有效的:

import subprocess
myOutput = subprocess.Popen("egrep -r --exclude=*{.git,.svn}* \"text\" ~/directory", stdout=subprocess.PIPE, shell=True).communicate()[0]
print "Output: ", myOutput
我已经在一个终端中使用Bash作为默认Shell命令进行了测试,效果很好

请注意,“grep-E”应该比“egrep”更受欢迎,后者现在已被弃用

您当然知道\也是Bash的转义字符,不是吗?我的意思是,“*”和花括号会被Bash消耗掉,因此不会交给grep。因此,你应该逃离他们

grep -Er --exclude=\*\{.git,.svn\}\* \"text\" ~/directory

这两个和分裂的论点,以避免外壳工程伟大!