Estou tentando executar um comando em uma nova janela do tmux. Um simples leitor de PDF de console/terminal. O script precisa de um argumento, um arquivo PDF, o nome do arquivo pode incluir espaços. Eu tentei isso:
#!/bin/bash
tmux new-window "pdftotext -layout -nopgbrk "${1}" - | less"
Funciona em arquivos sem espaços, por exemplo 1.pdf
. Eu tentei sh
em vez de bash
, $1
em "$1"
vez de "${1}"
, sem efeito.
tmux new-window
passa um comando para um shell. Isso é bom, seu comando é um pipeline e você precisa de um shell para processá-lo. Mas isso significa que haverá um shell que interpretará seu comando como uma string e só então o interpretará (comosh -c
faz).Parece que
tmux new-window
(comossh
) pode construir uma string de comando para o shell interno (no caso dessh
: remoto) a partir de vários argumentos obtidos. Para essas ferramentas, prefiro apresentar um único argumento.Você precisa fazer uma cotação para esse shell interno; ao mesmo tempo, você precisa citar o shell externo que interpreta o script. Em outras palavras, você precisa criar todo o comando tmux, portanto, depois que o shell externo substitui
$1
e remove as aspas, ele não é interpretado literalmente, as strings passadas paratmux new-window
formam um comando shell onde tudo o que precisa ser citado é citado corretamente. a casca interna.Uma ideia óbvia é incorporar algumas citações adicionais. Porém, isso é falho:
Um argumento contendo , , , ou
"
quebrará$
um`
comando\
e /ou outro. Pior ainda, isso cria uma vulnerabilidade de injeção de código (ou seja, para um argumento infeliz ou desonesto, seu script executará uma parte do argumento como código shell).!
'
Seu script usa Bash. Podemos pedir ao próprio Bash para expandir
$1
para um formato citado de maneira segura . Isso é feito peloQ
modificador :Não importa
$1
para onde se expanda, o invólucro externo se expandirá${1@Q}
para uma forma que parecerá adequadamente citada no invólucro interno.