Eu recomendo strongmente evitar o eval
- ele tende a funcionar muito bem em testes simples, mas, em seguida, na produção, alguns metacaracteres inesperados do shell aparecem e causam estragos. E se você tiver entrada do usuário na string, é praticamente garantido que você vai acabar com problemas de segurança. Considere o que aconteceria se alguém pudesse adicionar x'$(rm /somethingimportant)'y
à sua lista de padrões de arquivos.
Para situações como essa em que você está construindo um comando dinamicamente, as matrizes do bash são uma maneira muito melhor de ir. Use algo como:
namepatterns=(-name xxxx)
namepatterns+=(-o -name yyyyy -o -name "*.txt") # quotes prevent wildcard expansion
while read pattern; do
namepatterns+=(-o -name "$pattern")
done <patternfile.txt
find /etc "${namepatterns[@]}"
O "${array[@]}"
trata cada elemento da matriz como uma palavra shell, sem qualquer análise problemática (divisão de palavras, expansão de curingas) de que uma referência de variável sem aspas sofreria.
BTW, eu trapaceei um pouco no exemplo acima, adicionando o primeiro -name xxxx
primary ao array sem um -o
na frente dele. Se você estivesse construindo o array inteiramente em um loop, isso seria mais complicado:
namepatterns=()
while read pattern; do
namepatterns+=(-o -name "$pattern")
done <patternfile.txt
# At this point the array starts with "-o" -- not what you want
# So use array slicing to remove the first element:
namepatterns=("${namepatterns[@]:1}")
find /etc "${namepatterns[@]}"
Veja BashFAQ # 50: Estou tentando colocar um comando em uma variável, mas os casos complexos sempre falham! para mais discussão e opções para criar e armazenar comandos.