2

我在许多(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)

它不起作用,给出:

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]

当我复制并运行相同的命令(如上所示)时,find不会出错,并且 sed 要么没有输入文件,要么可以正常工作。

python片段有什么问题?

4

2 回答 2

9

您不是在尝试运行单个命令,而是在运行多个命令的 shell 管道,并且您尝试在不调用 shell 的情况下执行此操作。那是不可能的。您这样做的方式|只是 的参数之一find,这就是为什么find告诉您它不理解“路径必须先于表达式:|”的参数 错误。

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

但更好的解决方案是在 Python 中执行管道并将 shell 排除在外。请参阅文档中的用模块替换旧函数以subprocess获得解释,但我将展示一个示例。

同时,您永远不应该使用split拆分命令行。最好的解决方案是编写单独的参数列表,而不是将它们连接成一个字符串,只是为了将它们分开。如果必须这样做,请使用该shlex模块;这就是它的用途。但是在您的情况下,即使这样也无济于事,因为您正在逐字插入随机字符串,其中很容易包含空格或引号,并且没有任何方法(<code>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()

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

Python必须os.walk做与. _ 那么,为什么不使用它们呢?findxargsresed

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

于 2013-11-08T21:08:25.830 回答
1

问题是管道。要将管道与子流程模块一起使用,您必须通过shell=True.

于 2013-11-08T21:08:36.093 回答