Estou tentando fazer um script que precisa salvar um comando para ser executado como uma string. A string em questão precisa conter aspas e, ao tentar executá-la, o bash adiciona caracteres de aspas adicionais, o que em alguns casos faz com que o comando não seja executado conforme o esperado.
Aqui está um exemplo de script. O comando example
executado neste script de exemplo obviamente não faz nada e simplesmente dirá command not found
, no entanto, você ainda pode executar o script e ver do que estou falando porque adicionei -x
à #!/bin/bash
linha para que o comando exato que está sendo executado seja impresso .
Exemplo:
#!/bin/bash -x
#command typed explicitly
example -options "-i filename"
#command stored in string first
commandstring='example -options "-i filename"'
echo "running command: ${commandstring}"
${commandstring}
A saída da execução deste script para mim é (ignorando os dois erros de "comando não encontrado"):
+ example -options '-i filename'
+ commandstring='example -options "-i filename"'
+ echo 'running command: example -options "-i filename"'
running command: example -options "-i filename"
+ example -options '"-i' 'filename"'
Então você pode ver que a primeira linha é executada conforme o esperado, fornecendo o parâmetro de linha de comando:
-i filename
No entanto, embora o echo
comando imprima a string de uma forma que também seria executada perfeitamente, quando a string é colocada na linha de comando ela muda e o parâmetro que está sendo passado torna-se
'"-i' 'nome do arquivo"'
que contém caracteres de aspas adicionais, e isso está causando falha no comando real que estou usando em meu script real.
Existe alguma maneira de evitar isso?
Responder1
Se você estiver usando bash
, a maneira mais fácil de salvar exatamente um comando é colocá-lo em um array. Se o comando que você deseja executar for:
example -options "-i filename"
você pode salvá-lo em uma variável de array com:
commandline=(example -options "-i filename")
Então, você pode executar o comando salvo exatamente como está, expandindo @ a matriz entre aspas duplas:
"${commandline[@]}"
A principal coisa a saber aqui é que o shell trata os caracteres de aspas ( "'\
) de maneira diferente quando digitados diretamente na linha de comando e quando os encontra dentro de uma expansão de variável como em seu ${commandstring}
. Na linha de comando, os caracteres de aspas têm uma função especial de aspas. Dentro de uma expansão de parâmetro, eles são apenas caracteres normais não especiais. Portanto, "-i filename"
é uma única palavra quando digitada na linha de comando que é analisada como -i filename
, mas os mesmos caracteres em uma variável se expandem para as palavras "-i
e filename"
.
BashFAQ 50cobre este tópico com muito mais detalhes.