查找(bash命令)不适用于子流程吗? [英] Find (bash command) doesn't work with subprocess?

查看:75
本文介绍了查找(bash命令)不适用于子流程吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经在许多(python-django)模板中重命名了CSS类名称.但是,css文件广泛分布在多个目录中的多个文件中.我有一个python代码段,可从根目录开始重命名,然后递归重命名所有css文件.

I have renamed a css class name in a number of (python-django) templates. The css files however are wide-spread across multiple files in multiple directories. I have a python snippet to start renaming from the root dir and then recursively rename all the css files.

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不会获得任何输入文件,或者会起作用.

When I copy and run the same command (printed above), find doesn't error out and sed either gets no input files or it works.

python片段出了什么问题?

What is wrong with the python snippet?

推荐答案

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

You're not trying to run a single command, but a shell pipeline of multiple commands, and you're trying to do it without invoking the shell. That can't possibly work. The way you're doing this, | is just one of the arguments to find, which is why find is telling you that it doesn't understand that argument with that "paths must precede expression: |" error.

可以通过在您的Popen上添加shell=True来解决此问题.

You can fix that by adding shell=True to your Popen.

但是更好的解决方案是在Python中进行管道处理,并使外壳不进入其中.请参见用<文档中的c6>模块进行了解释,但我将显示一个示例.

But a better solution is to do the pipeline in Python and keep the shell out of it. See Replacing Older Functions with the subprocess Module in the docs for an explanation, but I'll show an example.

同时,您永远不要使用split拆分命令行.最好的解决方案是编写单独的参数列表,而不是将它们连接成一个字符串只是为了将它们分开.如果必须这样做,请使用shlex模块.这就是它的目的.但是对于您而言,即使那样也无济于事,因为您要逐字插入随机字符串,因为它们很容易在其中包含空格或引号,并且shlex或其他任何方式都无法重构数据中的数据.第一名.

Meanwhile, you should never use split to split a command line. The best solution is to write the list of separate arguments instead of joining them up into a string just to split them out. If you must do that, use the shlex module; that's what it's for. But in your case, even that won't help you, because you're inserting random strings verbatim, which could easily have spaces or quotes in them, and there's no way anything—shlex or otherwise—can reconstruct the data in the first place.

所以:

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()


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


But there's an even better solution here.

Python具有os.walk的作用与find相同,您可以轻松模拟xargs,但实际上并不需要这样做,它具有自己的re模块而不是.那么,为什么不使用它们呢?

Python has os.walk to do the same thing as find, you can simulate xargs easily, but there's really no need to do so, and it has its own re module to use instead of sed. So, why not use them?

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

Or, conversely, bash is much better at driving and connecting up simple commands than Python, so if you'd rather use find and sed instead of os.walk and re.sub, why write the driving script in Python in the first place?

这篇关于查找(bash命令)不适用于子流程吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆