关于python:如何转义os.system()调用?

关于python:如何转义os.system()调用?

How to escape os.system() calls?

使用os.system()时,通常需要转义文件名和其他作为参数传递给命令的参数。 我怎样才能做到这一点? 最好是可以在多个操作系统/外壳上运行的东西,尤其是bash。

我目前正在执行以下操作,但是请确保为此必须有一个库函数,或者至少是一个更优雅/更强大/更有效的选项:

1
2
3
4
5
6
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)))

编辑:我已经接受了使用引号的简单答案,不知道为什么我没有想到; 我猜是因为我来自Windows,"和"的行为略有不同。

关于安全性,我理解这个问题,但是在这种情况下,我对os.system()提供的快速简便的解决方案感兴趣,并且字符串的来源不是用户生成的,或者至少是由a输入的 受信任的用户(我)。


自python 3起,shlex.quote()即可满足您的需求。

(使用pipes.quote同时支持python 2和python 3)


这是我用的:

1
2
def shellquote(s):
    return"'" + s.replace("'","'\''") +"'"

外壳程序将始终接受带引号的文件名,并在将其传递给所涉及的程序之前删除其引号。值得注意的是,这避免了文件名包含空格或其他任何讨厌的shell元字符的问题。

更新:如果您使用的是Python 3.3或更高版本,请使用shlex.quote而不是自己滚动。


也许您有使用os.system()的特定原因。但是,如果没有,您可能应该使用subprocess模块。您可以直接指定管道,并避免使用外壳。

以下来自PEP324:

1
2
3
4
5
6
7
8
Replacing shell pipe line
-------------------------

output=`dmesg | grep hda`
==>
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep","hda"], stdin=p1.stdout, stdout=PIPE)
output = p2.communicate()[0]

也许subprocess.list2cmdline是更好的镜头?


请注意,pipes.quote实际上在Python 2.5和Python 3.1中已损坏,并且不安全使用-它不处理零长度参数。

1
2
3
4
>>> from pipes import quote
>>> args = ['arg1', '', 'arg3']
>>> print 'mycommand %s' % (' '.join(quote(arg) for arg in args))
mycommand arg1  arg3

参见Python问题7476;它已在Python 2.6和3.2及更高版本中修复。


注意:这是Python 2.7.x的答案。

根据消息来源,pipes.quote()是"可靠地将字符串作为/ bin / sh的单个参数引用"的一种方法。 (尽管从2.7版开始不推荐使用,但最终在Python 3.3中作为shlex.quote()函数公开了。)

另一方面,subprocess.list2cmdline()是一种"使用与MS C运行时相同的规则将参数序列转换为命令行字符串"的方法。

在这里,我们提供了平台无关的方式来引用命令行字符串。

1
2
3
4
5
6
7
8
9
10
11
12
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)

用法:

1
2
3
4
5
6
# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)


我相信os.system只会调用为用户配置的任何命令外壳,因此我认为您不能以独立于平台的方式进行操作。我的命令外壳可以是bash,emacs,ruby甚至quake3中的任何东西。这些程序中的某些程序并不期望您传递给它们的参数,即使它们这样做,也不能保证它们以相同的方式进行转义。


我使用的功能是:

1
2
3
4
5
6
7
8
def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\', '\\\')
        .replace('
"', '\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

即:我总是将参数用双引号引起来,然后用反斜杠将双引号内的特殊字符引起来。


真正的答案是:首先不要使用os.system()。请使用subprocess.call并提供未转义的参数。


如果您确实使用了system命令,我将尝试将os.system()调用中的内容列入白名单。

1
2
clean_user_input re.sub("[^a-zA-Z]","", user_input)
os.system("ls %s" % (clean_user_input))

subprocess模块??是一个更好的选择,我建议尽量避免使用os.system / subprocess之类的东西。


推荐阅读

    linux必须记忆的命令?

    linux必须记忆的命令?,工作,系统,地址,命令,信息,管理,目录,基础,网络,路径,L

    linux命令怎么编写?

    linux命令怎么编写?,系统,地址,工作,信息,命令,位置,环境,发行,标准,电脑,Lin

    程序执行linux命令?

    程序执行linux命令?,系统,工作,地址,环境,信息,管理,命令,文件,目录,程序,lin

    不常用的linux命令?

    不常用的linux命令?,工作,地址,系统,命令,信息,基础,网络,管理,标准,目录,Lin

    linux运维操作命令?

    linux运维操作命令?,系统,网络,基础,标准,工具,信息,工作,命令,软件,数据,lin

    linux常用命令中wr?

    linux常用命令中wr?,地址,工作,系统,命令,信息,目录,管理,网络,常用命令,控

    linux数据库同步命令?

    linux数据库同步命令?,信息,系统,汽车,车辆,服务,工作,通信,一致,分析,数据,D

    linux打开子目录命令?

    linux打开子目录命令?,系统,命令,标准,设备,工作,名称,信息,管理,密码,传播,l

    linux命令刷新加载?

    linux命令刷新加载?,系统,下来,工具,网上,命令,终端,环境变量,以下,文件,路

    linux命令怎么控制的?

    linux命令怎么控制的?,地址,工作,系统,标准,命令,电脑,基础,管理,灵活,网站,l

    linux退出程序命令?

    linux退出程序命令?,档案,管理,系统,命令,编辑,进程,模式,文件,程序,指令,lin

    linux磁盘命令dm?

    linux磁盘命令dm?,信息,设备,地址,软件,系统,工作,公司,下来,数据,磁盘,linux

    linux默认命令删除?

    linux默认命令删除?,系统,软件,名称,档案,命令,文件,目录,不了,电脑,文件夹,

    linux中启动软件命令?

    linux中启动软件命令?,环境,软件,电脑,系统,工具,位置,代码,设备,时间,情况,

    linux中的命令ls?

    linux中的命令ls?,信息,数据,名称,时间,标准,命令,文件,半导体,公司,网络,lin

    linux控制台停止命令?

    linux控制台停止命令?,地址,工具,平台,网络,下来,电脑,状态,命令,程序,进程,L

    linux执行2个命令?

    linux执行2个命令?,工作,系统,基础,命令,基础知识,信息,管理,在线,概念,第一

    linux命令行天气预报?

    linux命令行天气预报?,数据,软件,分析,技术,工具,环境,发展,基础,手机,系统,

    linux命令行基本特点?

    linux命令行基本特点?,系统,标准,基础,收费,网络,技术,设备,概念,公用,发行,L

    命令查看linux中断?

    命令查看linux中断?,网络,系统,状态,管理,地址,进程,命令,数据,信息,基础,Lin