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

2024-05-09 00:59:30 发布

您现在位置:Python中文网/ 问答频道 /正文

我在许多(pythondjango)模板中重命名了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)

它不起作用,给出:

^{pr2}$

当我复制并运行同一个命令(如上图所示)时,find不会出错,sed要么没有输入文件,要么就正常工作。在

python代码段有什么问题?在


Tags: 文件testimportrootfindcsssedcommand
2条回答

您不是在尝试运行一个命令,而是运行一个包含多个命令的shell管道,并且您试图在不调用shell的情况下运行它。那不可能奏效。这样做的方式,|只是find的一个参数,这就是为什么{}告诉你它不理解带有“paths must before expression:|”错误的参数。在

你可以把它加起来。在

但是一个更好的解决方案是用Python编写管道,并将shell排除在外。请参见文档中的Replacing Older Functions with the ^{} Module以获取解释,但我将展示一个示例。在

同时,不应该使用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()

但这里还有更好的解决方案。在

Python有os.walk来做与find相同的事情,您可以很容易地模拟xargs,但实际上没有必要这样做,而且它有自己的re模块来代替sed。那么,为什么不使用它们呢?在

或者,相反地,bash在驱动和连接简单命令方面比Python好得多,因此,如果您宁愿使用find和{},而不是{}和re.sub,那么为什么首先用Python编写驱动脚本呢?在

问题出在管子上。要在subprocess模块中使用管道,必须传递shell=True。在

相关问题 更多 >

    热门问题