[python] os.system () 호출을 이스케이프하는 방법은 무엇입니까?

os.system ()을 사용할 때 종종 명령에 매개 변수로 전달 된 파일 이름 및 기타 인수를 이스케이프해야합니다. 어떻게 할 수 있습니까? 여러 운영 체제 / 쉘에서 작동하지만 특히 bash에서는 작동하는 것이 좋습니다.

저는 현재 다음을 수행하고 있지만이를위한 라이브러리 함수 또는 적어도 더 우아하고 / 튼튼하고 / 효율적인 옵션이 있어야합니다.

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 ()이 제공하는 빠르고 쉬운 솔루션에 관심이 있으며 문자열의 소스는 사용자가 생성하지 않았거나 최소한 사용자가 입력 한 것입니다. 신뢰할 수있는 사용자 (나).



답변

이것이 내가 사용하는 것입니다.

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

쉘은 항상 따옴표로 묶인 파일 이름을 받아들이고 문제의 프로그램에 전달하기 전에 주변 따옴표를 제거합니다. 특히 이것은 공백이나 기타 불쾌한 쉘 메타 문자를 포함하는 파일 이름의 문제를 방지합니다.

업데이트 : Python 3.3 이상을 사용하는 경우 직접 롤링하는 대신 shlex.quote 를 사용 하십시오.


답변

shlex.quote() 파이썬 3 이후로 원하는 것을 수행합니다.

( pipes.quotepython 2와 python 3을 모두 지원하는 데 사용 )


답변

.NET을 사용하는 특별한 이유가있을 수 있습니다 os.system(). 그러나 그렇지 않다면 아마도 모듈 을 사용해야 할 것입니다.subprocess . 파이프를 직접 지정하고 셸 사용을 피할 수 있습니다.

다음은 PEP324 에서 가져온 것입니다 .

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에서 깨졌고 사용하기에 안전하지 않습니다. 길이가 0 인 인수를 처리하지 않습니다.

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

Python issue 7476을 참조하십시오 . Python 2.6 및 3.2 이상에서 수정되었습니다.


답변

주의 : 이것은 Python 2.7.x에 대한 답변입니다.

에 따르면 소스 , pipes.quote()“할 수있는 방법이다 안정적에 대해 하나의 인수로 문자열 인용 / 빈 / SH는 “. (단, 버전 2.7부터 사용되지 않고 마침내 Python 3.3에서 shlex.quote()함수 로 공개적으로 노출되었습니다 .)

다른 한편으로 , subprocess.list2cmdline()“할 수있는 방법 은 AS와 동일한 규칙을 사용하여 명령 행 문자열로 인수의 순서를 번역 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)


답변

나는 os.system이 사용자를 위해 구성된 명령 쉘을 호출한다고 믿기 때문에 플랫폼 독립적 인 방식으로 할 수 있다고 생각하지 않습니다. 내 명령 셸은 bash, emacs, ruby ​​또는 quake3의 모든 것이 될 수 있습니다. 이 프로그램 중 일부는 당신이 그들에게 전달하는 주장의 종류를 기대하지 않으며 그들이 그렇게하더라도 그들이 같은 방식으로 탈출한다는 보장이 없습니다.