2012-04-03 41 views
37
import os 

import subprocess 

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 

out,err = proc.communicate() 

print out 

此脚本应打印所有带.bc后缀的文件,但它会返回一个空列表。如果我在命令行中手动执行ls * .bc,它将起作用。在脚本中做['ls','test.bc']也可以工作,但由于某些原因,星号不起作用。任何想法?Python子流程通配符使用

+0

相关:通配符不能在使用shlex的子流程调用中工作](http:// stackoverf low.com/q/7156892/4279) – jfs 2014-05-16 03:42:54

回答

41

您需要提供shell=True才能通过shell解释器执行该命令。 但是,如果你这样做,你不能再提供一个列表作为第一个参数,因为参数会被引用。相反,指定原始命令行,你希望它被传递给shell:

proc = subprocess.Popen('ls *.bc', shell=True, 
            stdout=subprocess.PIPE, 
            stderr=subprocess.PIPE) 
+0

谢谢,这工作得很好。我在互联网上找到的一些例子有一个列表作为他们的第一个参数出于某种原因 – Cemre 2012-04-03 16:06:42

+9

@Cemre:这通常是可取的,因为你*不希望shell解释参数。假设你将用户输入传递给''ls'+ user_supplied_pa​​th'中的命令。用户可以输入路径';关机-s“,系统将停止!如果你使用'['ls',user_supplied_pa​​th]',你可以防止这种注入。 – 2012-04-03 16:09:25

37

扩大*水珠是外壳的一部分,但默认情况下subprocess通过shell发送你的命令,所以该命令(第一个参数,ls)被执行,然后文字*被用作参数。

这是一件好事情,请参阅the warning block in the "Frequently Used Arguments" section,子流程文档。它主要讨论安全影响,但也可以帮助避免愚蠢的编程错误(因为没有魔法外壳字符担心)

我主要抱怨shell=True通常意味着有一个更好的方式去解决这个问题 - 你的榜样,你应该使用the glob module

import glob 
files = glob.glob("*.bc") 
print files # ['file1.bc', 'file2.bc'] 

这将是更快的(无进程启动开销),更可靠,跨平台(不依赖具有ls命令的平台上)

+0

'subprocess不通过shell发送你的命令'为什么? 你能提供任何参考吗?谢谢 – Stallman 2015-11-22 15:03:13

+0

加上它提供了一个python对象来处理和操作。这应该是选定的答案。更多'python'友好。 – Cyan 2016-05-21 13:52:11