Eu preciso passar strings armazenadas em uma variável para uma string de comando find.
O que eu faço:
s="\( ! -path \"/path/to/1/Recycle Bin\" \) -or"
s="${s} \( ! -path \"/path/to/2/Recycle Bin\" \)"
exec=$(find "/path/to/Recycle Bin" -type d $s)
Resultado:
find: paths must precede expression: `\('
Se eu fizer:
exec=$(find "/path/to/Recycle Bin" -type d \( ! -path "/path/to/1/Recycle Bin" \) -or \( ! -path "/path/to/2/Recycle Bin" \))
Funciona.
O que estou fazendo errado?
Se sua variável pode não conter o que você pensa, use
para ver o resultado de cada expansão.
O shell processa as barras invertidas e aspas duplas nos
find
comandos, mas não os processa da mesma maneira quando expande sua variável...Na linha de comando, escrevemos:
Se você executou
set -x
, pode ver o que o Bash faz disso e o que realmente é passado parafind
:A remoção de aspas em sua variável não acontece (você coloca os caracteres
\
e"
lá, então você quer que eles sejam mantidos, certo? Esses caracteres "resultaram da expansão" então eles não são removidos ) (\"
tornou -se"
quando você o atribuiu como você presumivelmente pretendida porque em aspas duplas barra invertida cita os caracteres\$`"
), mas a divisão de palavras faz:Citando a variável corrige a divisão de palavras incorretas, mas também evita a tokenização :
Praticamente qualquer coisa que você fizer com essas duas cordas resultará em
find
ver a coisa errada. Conseguir que sua variável contenha apenas e exatamente uma string que se expande'(' '!' -path '/path/to/1/Recycle Bin' ')' -or '(' '!' -path '/path/to/2/Recycle Bin' ')'
é uma guerra de citações que eu pessoalmente não poderia vencer.Algo assim vai funcionar bem
Você também pode se safar se remover a necessidade de aspas, não usando caminhos com espaços - se você remover as barras invertidas e aspas duplas:
Talvez se você explicar por que deseja fazer dessa maneira, alguém poderá sugerir uma solução alternativa melhor.
IMHO, o único confiável para fazer isso no bash é usar uma matriz.
Arrays devidamente citados permitem que você construa uma linha de comando que consiste em argumentos individualmente analisáveis que podem conter espaços em branco.
Ex.
Podemos ver o que o shell verá imprimindo os elementos individuais, um por linha: