查找(bash命令)不适用于子流程吗? [英] Find (bash command) doesn't work with subprocess?
问题描述
我已经在许多(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要好得多,因此,如果您宁愿使用find
和sed
而不是os.walk
和re.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屋!