为什么运行Python子进程grep忽略--exclude-dir标志

时间:2018-08-07 10:52:50

标签: python command-line grep subprocess

从终端执行此命令时:

\grep -inH -r --exclude-dir={node_modules,.meteor,.git} -e test -- /Users/nelsyeung/Sites/foo

它输出正确的结果,其中排除了--exclude-dir目录。

以下Python脚本理论上应该执行完全相同的操作:

#!/usr/bin/env python3
from subprocess import Popen, PIPE

cmd = 'grep -inH -r --exclude-dir={node_modules,.meteor,.git} -e test -- /Users/nelsyeung/Sites/foo'
with Popen(cmd.split(), stdout=PIPE, bufsize=1, universal_newlines=True) as p:
    for l in p.stdout:
        print(l)

但是--exclude-dir标志似乎被忽略了,也就是说,它也来自node_modules.meteor.git的grep。

问题:为什么上面的代码输出的结果与仅执行命令时不同?

请注意,这比我寻找替代解决方案更多的是理论问题,因为Python代码基本上来自我使用的插件,我只能在其中为命令提供标志,仅此而已令人惊讶的是,传入--exclude-dir并没有任何作用。如果上面的代码有问题,请指出来。

系统信息:

  • 操作系统:macOS 10.13.6
  • Python:3.7.0
  • grep:(BSD grep)2.5.1-FreeBSD(支持--exclude-dir

1 个答案:

答案 0 :(得分:2)

--exclude-dir={dir1,dir2} is expanded to

--exclude-dir=dir1 --exclude-dir=dir2

通过外壳,而不是grep。 Popen默认使用shell=False

所以改用

from subprocess import Popen, PIPE

cmd = '''grep -inH -r --exclude-dir=node_modules --exclude-dir=.meteor 
         --exclude-dir=.git -e test -- /Users/nelsyeung/Sites/foo'''
with Popen(cmd.split(), stdout=PIPE, bufsize=1, universal_newlines=True) as p:
    for l in p.stdout:
        print(l)

(请注意,虽然使用shell=True可能是另一种选择,但由于security issues而不是首选方法。)