2014-02-10 142 views
3

我有一个python脚本,它可以根据给定的输入生成一些shell命令。问题是,当它试图执行生成的命令时,它会失败,但是当我自己运行生成的命令(即从命令行)时,它们会成功执行。shell命令从python失败,从shell中可以正常工作

这里是生成的命令:

find /home/me/downloader/0-29/ -type f | grep -i .rpm$ | xargs -i cp {} /home/me/downloader/builds/0-29/

下面是当它是由python脚本运行错误消息:

find: paths must precede expression: | 
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression] 

你能帮助我了解的问题是什么?

UPD:这里是功能我使用的执行产生的命令:

def exec_command(command): 
     process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) 
     output = process.communicate()[0] 
     return output

+0

你是如何从python执行该行的?提供一些代码? – theAlse

+1

你可能需要在python中引用你的命令来执行... – user3

回答

2

由于您的命令是一个管道,你必须设置shell=True,这样子会发送命令,如,对外壳:

command = 'find /home/me/downloader/0-29/ -type f | grep -i .rpm$ | xargs -i cp {} /home/me/downloader/builds/0-29/' 
subprocess.call(command, shell=True) 

或者,

process = subprocess.Popen(command, shell=True) 
output = process.communicate()[0] 
return output 

另外,不要在具有管道的命令上使用python进行分割。这将导致find作为其参数之一而不是作为shell运算符传递|

还显示出该命令可以简化为:

command="find /home/me/downloader/0-29/ -type f -iname '*.rpm' -exec cp {} /home/me/downloader/builds/0-29/ \;" 

由于上述不再是一个管道,它可以与一个小的修改,被分离并给出壳到子过程=假。修改是在'*.rpm'附近的单引号是为了保护glob不受shell扩展的影响。在shell = False的情况下,shell不会删除它们。所以,我们必须。对于壳=假,并与command.split()使用:

command="find /home/me/downloader/0-29/ -type f -iname *.rpm -exec cp {} /home/me/downloader/builds/0-29/ \;" 
+0

我认为你在简化版本中搞砸了你的引号。 – user2357112

+0

@ user2357112谢谢。修复。 – John1024

+0

只有当命令行由shell处理时,'* .rpm'附近的单引号才有必要,以防止模式扩展;在将文字字符串传递给'find'之前,shell会删除引号。用'shell = False',你想把单引号留下。 – chepner

1

我相信你做什么是你开始叫find有许多参数的单个程序,含。 |grepxargs - 这些都不是找到的参数。

想要做什么大概是问的bash运行find然后通过管道将结果向grep,等做到这一点的方法之一是执行一个命令叫bash两个参数(-c)和整个字符串包括。管道命令,例如

process = subprocess.Popen(["bash", "-c", "cat /etc/issue | grep a"], stdout=subprocess.PIPE) 
output=process.communicate()[0] 
print output