문제

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() Python 3부터 원하는 것을 수행합니다.

(사용 pipes.quote Python 2와 Python 3을 모두 지원하려면)

아마도 당신은 이 제품을 사용하는 특별한 이유가 있을 것입니다. 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 문제 7476;Python 2.6 및 3.2 이상에서 수정되었습니다.

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

알아채다:이것은 Python 2.7.x에 대한 답변입니다.

에 따르면 원천, pipes.quote() "라는 방법이다.문자열을 단일 인수로 안정적으로 인용합니다. /bin/sh".(그렇긴 하지만 버전 2.7부터 더 이상 사용되지 않음 마침내 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)

내가 사용하는 기능은 다음과 같습니다.

def quote_argument(argument):
    return '"%s"' % (
        argument
        .replace('\\', '\\\\')
        .replace('"', '\\"')
        .replace('$', '\\$')
        .replace('`', '\\`')
    )

그건:나는 항상 인수를 큰따옴표로 묶은 다음 큰따옴표 안의 특수 문자만 백슬래시로 묶습니다.

시스템 명령을 사용한다면 os.system() 호출에 포함되는 내용을 화이트리스트에 추가해 보겠습니다.예를 들어..

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

subprocess 모듈이 더 나은 옵션이므로 가능하면 os.system/subprocess와 같은 모듈은 사용하지 않는 것이 좋습니다.

실제 대답은 다음과 같습니다.사용하지 마세요 os.system() 우선.사용 subprocess.call 대신 이스케이프되지 않은 인수를 제공하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top