Como escapar os.system () chamadas?

votos
98

Ao usar os.system () é muitas vezes necessário para escapar nomes de arquivos e outros argumentos passados ​​como parâmetros para comandos. Como posso fazer isso? De preferência algo que iria trabalhar em vários operacionais sistemas / conchas mas em particular para a festança.

Atualmente estou fazendo o seguinte, mas tenho certeza que deve haver uma função de biblioteca para isso, ou pelo menos uma opção mais elegante / robusta / eficiente:

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)))

Edit: Eu aceitei a resposta simples de usar aspas, não sei por que eu não tinha pensado nisso; Acho que é porque eu vim a partir do Windows, onde e se comportam um pouco diferente.

Em relação à segurança, entendo a preocupação, mas, neste caso, eu estou interessado em uma solução rápida e fácil, que os.system () fornece, ea fonte das cordas é ou não gerado pelo usuário ou pelo menos entrou por um usuário confiável (me).

Publicado 30/08/2008 em 10:27
fonte usuário
Em outras línguas...                            


10 respostas

votos
133

shlex.quote() faz o que quiser desde python 3.

(Utilize pipes.quotepara suportar tanto Python 2 e 3)

Respondeu 11/05/2009 em 13:06
fonte usuário

votos
69

Isto é o que eu uso:

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

O shell sempre aceitará um nome de arquivo entre aspas e remover as aspas antes de passá-lo para o programa em questão. Notavelmente, isso evita problemas com nomes de arquivos que contêm espaços ou qualquer outro tipo de metacharacter shell desagradável.

Atualização : Se você estiver usando o Python 3.3 ou posterior, use shlex.quote em vez de rolar o seu próprio.

Respondeu 30/08/2008 em 11:13
fonte usuário

votos
54

Talvez você tenha um motivo específico para usar os.system(). Mas se não você provavelmente deve estar usando o subprocessmódulo . Você pode especificar os tubos diretamente e evitar o uso da casca.

O seguinte é de 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]
Respondeu 30/08/2008 em 11:15
fonte usuário

votos
8

Talvez subprocess.list2cmdlineé um tiro melhor?

Respondeu 25/05/2012 em 08:54
fonte usuário

votos
4

Note-se que pipes.quote é realmente quebrado em Python 2.5 e Python 3.1 e não é seguro para usar - Ele não lida com argumentos de comprimento zero.

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

Ver questão Python 7476 ; que foi corrigido no Python 2.6 e 3.2 e mais recentes.

Respondeu 11/12/2009 em 00:03
fonte usuário

votos
3

Note : Esta é uma resposta para Python 2.7.x.

De acordo com a fonte , pipes.quote()é uma forma de " Reliably citar uma string como um único argumento para / bin / sh ". (Embora seja preterido uma vez que a versão 2.7 e finalmente exposto ao público em Python 3.3 como a shelx.quote()função).

Por outro lado , subprocess.list2cmdline()é uma forma de " Traduzir uma seqüência de argumentos em uma seqüência de linha de comando, usando as mesmas regras que o tempo de execução MS C ".

Aqui estamos nós, a maneira independente de plataforma de citar cordas para linhas de comando.

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)

Uso:

# Quote a single argument
print quote_args(['my argument'])

# Quote multiple arguments
my_args = ['This', 'is', 'my arguments']
print quote_args(my_args)
Respondeu 13/04/2015 em 03:26
fonte usuário

votos
3

Acredito que os.system apenas invoca tudo o shell de comando é configurado para o usuário, então eu não acho que você pode fazê-lo de uma forma independente de plataforma. Meu shell de comando poderia ser qualquer coisa de bash, emacs, rubi, ou mesmo Quake3. Alguns desses programas não estão esperando o tipo de argumentos que você está passando para eles e mesmo que eles fizeram não há garantia de que eles fazem a sua fuga da mesma maneira.

Respondeu 30/08/2008 em 10:43
fonte usuário

votos
1

A função que eu uso é:

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

isto é: Eu sempre colocar o argumento entre aspas, e em seguida barra invertida-citar os únicos caracteres especiais dentro de aspas.

Respondeu 03/10/2010 em 22:21
fonte usuário

votos
-2

A verdadeira resposta é: Não use os.system()em primeiro lugar. Use subprocess.callem vez disso e fornecer os argumentos unescaped.

Respondeu 25/04/2013 em 09:44
fonte usuário

votos
-2

Se você usar o comando do sistema, gostaria de tentar e whitelist o que vai para a chamada os.system () .. Por exemplo ..

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

O módulo subprocesso é uma opção melhor, e eu recomendaria a tentar evitar o uso de qualquer coisa como os.system / subprocess sempre que possível.

Respondeu 30/08/2008 em 12:43
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more