subprocess wildcard usage

import os


import subprocess


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


out,err = proc.communicate()


print out

This script should print all the files with .bc suffix however it returns an empty list. If I do ls *.bc manually in the command line it works. Doing ['ls','test.bc'] inside the script works as well but for some reason the star symbol doesnt work.. Any ideas ?

38483 次浏览

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

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

展开 * globb 是 shell 的一部分,但是默认情况下,subprocess通过 shell 发送命令,因此执行命令(第一个参数,ls) ,然后使用文本 *作为参数。

这是一件好事,请参阅子流程文档的 “常用参数”部分中的警告块。它主要讨论安全隐患,但也可以帮助避免愚蠢的编程错误(因为不需要担心神奇的 shell 字符)

我对 shell=True的主要抱怨是,它通常意味着有一个更好的解决问题的方法——根据你的例子,你应该使用 glob模块:

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

这将更快(没有进程启动开销)、更可靠和跨平台(不依赖于具有 ls命令的平台)

除了执行 shell=True之外,还要确保没有引用您的路径。否则它将不会被 shell 展开。

如果路径可能有特殊字符,则必须手动转义它们。