使用包含带有子进程

时间:2017-06-07 20:40:43

标签: python python-2.7

我在使用子进程模块时遇到了一些问题。我希望模块运行相当于'ls -l“/ path / to / file /的shell命令,其中包含目录中的可能空格/或名称中的空格”'。当文件名不是变量时,子进程工作正常。如果文件名是包含引号的变量,则它不起作用。

不起作用的代码:

import subprocess

archive_file_list = "/var/tmp/list"
archive = open(archive_file_list, "r")

for line in archive:
    noreturnline = line[:-1]
    quotedline = "\"" + noreturnline + "\""
    if extension == "zip":
        print quotedline
        archivelist = subprocess.check_output(['ls', '-l', quotedline])
        print archivelist

有效的代码:

archivelist = subprocess.check_output(['ls', '-l', "/path/to/file/with possible space in directory/or with space in name"])

以下是不起作用的代码的输出:

"/path/to/file/with possible space in directory/or with space in name"
ls: cannot access "/path/to/file/with possible space in directory/or with space in name" No such file or directory
Traceback (most recent call last):
File "./archive_test.py", line 12, in <module>
archivelist = subprocess.check_output(['ls', '-l', quotedline])
File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['ls', '-l', '"/path/to/file/with possible space in directory/or with space in name"']' returned non-zero exit status 2

在您提出之前 - 是的,我已经通过从命令行运行'ls -l'来验证“/ path / to / file /目录中的可能空间/或名称中的空格”确实存在。

任何帮助将不胜感激。提前谢谢。

1 个答案:

答案 0 :(得分:3)

第一个命令中的

(这是最好的选择):

archivelist = subprocess.check_output(['ls', '-l', "/path/to/file/with possible space in directory/or with space in name"])

第三个参数实际上是/path/to/file/with possible space in directory/or with space in name(没有引号),它是存在的文件名,命令有效。

由于shell=True甚至没有设置,所以命令直接传递给exec,参数按原样传递:空格&amp;保留其他字符。

如果您添加更多引号,则不会将其删除,并且它们会逐字传递给ls

由于没有名为"/path/to/file/with possible space in directory/or with space in name"的文件(带引号),因此找不到文件/目录。

另一种(脏)调用命令的方式:将完整命令作为字符串传递(不作为参数列表)。在这种情况下,这将起作用(至少在Windows上没有shell=Truesubprocess似乎处理参数拆分,似乎在类Unix系统上需要shell=True

subprocess.check_output('ls -l "/path/to/file/with possible space in directory/or with space in name"')

但是你的第一种方法更清晰,特别是如果你不知道目录名,因为它是一个参数。让subprocess为你做繁重的工作。

在类Unix系统上,使用最后一种方法需要shell=True,但是你会将程序暴露给任何开放系统调用之类的恶意攻击(将;rm -rf /附加到文件名,评估例如子壳)

最后注意事项:如果您 计划使用ls并解析其输出,请不要执行此操作(http://mywiki.wooledge.org/ParsingLs),请使用标准os.listdiros.path.getsize/getmtime&amp; os.stat要求您获取所需信息。