find comando com parâmetros na variável

3
> find /etc -name 'shells'
/etc/shells     # good !!

> SEARCH="-name 'shells'"; find /etc $SEARCH
# nothing found - bad !!

Por que o comando "find" não pode aceitar params na variável?

Outros comandos funcionam bem nesse modo. Está provavelmente relacionado com espaços e análise. Como posso, a princípio, construir params na variável e depois executar "find" com este params?

Para ser claro, eu quero fazer a cadeia de -name xxxx -o -name yyyyy -o -name zzzzz e, em seguida, encontrar todos os arquivos em uma execução

    
por xoid 21.07.2015 / 08:55

4 respostas

3

o seu problema é que as aspas simples não são interpretadas como tal, mas como estando nos seus parâmetros.

Você acha que executou isso:

find /etc -name 'shells'

Quando na verdade você executou isso:

find /etc -name \'shells\'

Tenha em mente : no bash, as aspas simples entre aspas duplas não são ignoradas.

Portanto, a solução é não colocar aspas simples:

SEARCH="-name shells"; find /etc $SEARCH

Uma solução melhor é usar aspas e, em seguida, usar eval:

SEARCH="-name 'shells'"; eval " find /etc $SEARCH"

Problema de segurança : nunca, nunca use informações fornecidas pelo usuário em um argumento eval.

    
por 21.07.2015 / 12:13
1

tente

eval find /etc $SEARCH
  • eval avaliará a linha após a expansão da variável
por 21.07.2015 / 09:27
0

Experimente a opção -name da seguinte forma:

SEARCH="shells"; find /etc -name $SEARCH

Dê uma olhada em esta pergunta para algumas opções.

    
por 21.07.2015 / 09:05
0

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.

    
por 23.07.2015 / 02:07

Tags