我在使用子进程模块时遇到了一些问题。我希望模块运行相当于'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 /目录中的可能空间/或名称中的空格”确实存在。
任何帮助将不胜感激。提前谢谢。
答案 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=True
,subprocess
似乎处理参数拆分,似乎在类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.listdir
,os.path.getsize/getmtime
&amp; os.stat
要求您获取所需信息。