Find(bash命令)不适用于子进程?

0xc*_*0de 2 python subprocess sed find xargs

我在一些(python-django)模板中重命名了一个css类名.然而,css文件广泛分布在多个目录中的多个文件中.我有一个python片段开始从根目录重命名,然后递归重命名所有的CSS文件.

from os import walk, curdir
import subprocess

COMMAND = "find %s -iname *.css | xargs sed -i s/[Ff][Oo][Oo]/bar/g"
test_command = 'echo "This is just a test. DIR: %s"'

def renamer(command):
  print command  # Please ignore the print commands.
  proccess = subprocess.Popen(command.split(), stdout = subprocess.PIPE)
  op = proccess.communicate()[0]
  print op

for root, dirs, files in walk(curdir):
  if root:
    command = COMMAND % root
    renamer(command)
Run Code Online (Sandbox Code Playgroud)

它不起作用,给出:

find ./cms/djangoapps/contentstore/management/commands/tests -iname *.css | xargs sed -i s/[Ee][Dd][Xx]/gurukul/g
find: paths must precede expression: |
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]

find ./cms/djangoapps/contentstore/views -iname *.css | xargs sed -i s/[Ee][Dd][Xx]/gurukul/g
find: paths must precede expression: |
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression]
Run Code Online (Sandbox Code Playgroud)

当我复制并运行相同的命令(上面打印),find没有错误输出和sed要么没有输入文件或它的工作原理.

python片段有什么问题?

aba*_*ert 8

您不是要尝试运行单个命令,而是尝试运行多个命令的shell管道,并且您尝试在不调用shell的情况下执行此操作.那不可能奏效.你这样做的方式|只是其中一个参数find,这就是为什么find告诉你它不理解那个"路径必须在表达式之前的参数:|"的原因.错误.

可以通过添加shell=True到您的Popen.

但更好的解决方案是在Python中执行管道并保持shell不受其影响.有关说明,请参阅在文档中用subprocess模块替换较旧的函数,但我将展示一个示例.

同时,您永远不应该使用split拆分命令行.最好的解决方案是编写单独的参数列表,而不是将它们连接成一个字符串,只是为了将它们拆分出来.如果必须这样做,请使用该shlex模块; 这就是它的用途.但在你的情况下,即使这样也无济于事,因为你逐字插入随机字符串,这些字符串很容易在其中包含空格或引号,并且没有任何方法shlex或其他方式可以在一开始就重建数据.

所以:

pfind = Popen(['find', root, '-iname', '*.css'], stdout=PIPE)
pxargs = Popen(['xargs', 'sed', '-i', 's/[Ff][Oo][Oo]/bar/g'], 
               stdin=pfind.stdout, stdout=PIPE)
pfind.stdout.close()
output = pxargs.communicate()
Run Code Online (Sandbox Code Playgroud)

但这里有一个更好的解决方案.

Python必须os.walk做同样的事情find,你可以xargs轻松地模拟,但实际上没有必要这样做,并且它有自己的re模块来代替sed.那么,为什么不使用它们呢?

或者,相反,bash在驱动和连接简单命令方面要比Python好得多,所以如果你宁愿使用findsed不是os.walkre.sub,为什么首先用Python编写驱动脚本呢?