Python 如何转义os.system()调用?
使用os.system()时,通常需要转义文件名和作为参数传递给命令的其他参数。我该怎么做?最好是能够在多个操作系统/shell上工作,尤其是bash 我目前正在做以下工作,但我确信必须有一个库函数来实现这一点,或者至少有一个更优雅/健壮/高效的选项:Python 如何转义os.system()调用?,python,shell,escaping,Python,Shell,Escaping,使用os.system()时,通常需要转义文件名和作为参数传递给命令的其他参数。我该怎么做?最好是能够在多个操作系统/shell上工作,尤其是bash 我目前正在做以下工作,但我确信必须有一个库函数来实现这一点,或者至少有一个更优雅/健壮/高效的选项: def sh_escape(s): return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ") os.system("cat %s | grep something
def sh_escape(s):
return s.replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
os.system("cat %s | grep something | sort > %s"
% (sh_escape(in_filename),
sh_escape(out_filename)))
编辑:我已经接受了使用引号的简单答案,不知道为什么我没有想到这一点;我猜是因为我来自“和”行为有点不同的窗口
关于安全性,我理解这个问题,但在本例中,我对os.system()提供的一个快速简便的解决方案感兴趣,字符串的来源不是用户生成的,或者至少是由可信用户(me)输入的.我相信os.system只会调用为用户配置的任何命令shell,因此我认为您无法以独立于平台的方式进行调用。我的命令shell可以是bash、emacs、ruby甚至quake3中的任何命令。这些程序中的一些程序并不期望您传递给它们的参数类型,即使它们在那里传递了不能保证它们以同样的方式逃逸。这就是我使用的:
def shellquote(s):
return "'" + s.replace("'", "'\\''") + "'"
shell将始终接受带引号的文件名,并在将其传递给相关程序之前删除周围的引号。值得注意的是,这避免了包含空格或任何其他讨厌的shell元字符的文件名出现问题
更新:如果您使用的是Python 3.3或更高版本,请使用而不是使用自己的。也许您使用
os.system()
有特定的原因。但如果不是,您可能应该使用。您可以直接指定管道,避免使用shell
以下资料来自:
从Python3开始做你想要的
(用于同时支持python 2和python 3)请注意,pipes.quote在python 2.5和python 3.1中实际上已损坏,使用起来不安全--它不处理零长度参数
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1 arg3
请参阅;它已在Python 2.6和3.2及更新版本中修复。我使用的函数是:
def quote_argument(argument):
return '"%s"' % (
argument
.replace('\\', '\\\\')
.replace('"', '\\"')
.replace('$', '\\$')
.replace('`', '\\`')
)
也就是说:我总是用双引号将参数括起来,然后用反斜杠将双引号内唯一的特殊字符引起来。也许
子流程。list2cmdline
是更好的选择?注意:这是Python 2.7.x的答案
根据,pipes.quote()
是一种“可靠地将字符串作为/bin/sh的单个参数引用”的方法(尽管它最终在Python 3.3中公开为shlex.quote()
函数)
在上,subprocess.list2cmdline()
是一种“使用与MS C运行时相同的规则将参数序列转换为命令行字符串”的方法
这里是独立于平台的为命令行引用字符串的方式
import sys
mswindows = (sys.platform == "win32")
if mswindows:
from subprocess import list2cmdline
quote_args = list2cmdline
else:
# POSIX
from pipes import quote
def quote_args(seq):
return ' '.join(quote(arg) for arg in seq)
用法:
# Quote a single argument
print quote_args(['my argument'])
# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)
@pixelbeat:这正是他关闭单引号,添加转义文字单引号,然后再次打开单引号的原因。虽然这不是shellquote函数的责任,但值得注意的是,如果在该函数的返回值之前出现一个不带引号的反斜杠,这仍然会失败。Mo罗尔:确保在您可以信任为安全的代码中使用此选项-(例如部分硬编码命令)-不要将其附加到其他未引用的用户输入中。请注意,除非您绝对需要shell功能,否则您可能应该使用Jamie的建议。类似于此的内容现在正式提供为。此答案中提供的函数在shell引用方面比
shlex
或管道
做得更好。这些pythondules错误地认为只有特殊字符才需要引用,这意味着shell关键字(如time
、case
或while
)将在不期望出现这种行为时进行分析。因此,我建议在此回答中使用单引号例程,因为它不试图“聪明”,因此没有那些愚蠢的边缘情况。您使用的Python版本是什么?版本2.6似乎生成了正确的输出:mycommand arg1“”arg3(这是两个单引号加在一起,尽管堆栈上的字体溢出很难说!)期望一个大部分或完全符合POSIX的shell(至少在所有地方都是如此,但Windows除外,而且你知道你有什么“shell”).os.system不使用$SHELL,至少在这里不使用。还有命令.mkarg
。它还添加了一个前导空格(在引号之外)这可能是可取的,也可能是不可取的。有趣的是,它们的实现彼此之间有很大的不同,而且比Greg Hewgill的答案复杂得多。出于某种原因,pipes.quote
没有被提及,两者都没有文档化;command.mkarg
在3.x中被弃用并删除,而pipes.quote仍然保留.Correction:正式记录在3.3中,pipes.quote()
保留以保持兼容性。[管道在Windows上不工作-添加单引号而不是双引号。这看起来相当不错。有趣的是,它没有记录在案…(至少)它没有正确转义\:子流程.list2cmdline([“,”\\,“,”)
给出了“\\”
它不会转义shell扩展符号子进程。list2cmdline()仅适用于Windows?@JS是,list2cmdline
符合Windows cmd.exe语法().shlex.quote
符合Unix bourne shell语法,但这通常不是必需的,因为Unix对直接传递参数有很好的支持。Windows几乎要求传递包含所有参数的单个字符串(因此需要正确转义)。注意安全问题!例如,如果out_文件名为foo.txt;rm-rf/恶意用户可以直接添加更多命令
# Quote a single argument
print quote_args(['my argument'])
# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)