Em shells do tipo Bourne (exceto zsh ), deixar uma expansão de variável sem aspas no contexto da lista é o operador split + glob . Em:
cond="-name '*.txt'"; echo $cond
O conteúdo de $cond é dividido primeiro de acordo com o valor da variável especial $IFS . Por padrão, isso é no espaço ASCII, na guia e nos caracteres de nova linha.
Então, isso é divisão em -name e '*.txt' . Então a parte glob é aplicada. Para cada uma dessas palavras que contém caracteres curinga (aqui * no segundo), a palavra é expandida para a lista de arquivos que correspondem a esse padrão ou deixada intacta se nenhum arquivo for correspondido. Portanto, '*.txt' se expandiria para a lista de arquivos no diretório atual cujo nome começa com ' e termina em .txt' ou para '*.txt' se nenhum arquivo corresponder.
Essa lista de palavras é então passada como argumentos separados para echo . Se nenhum arquivo corresponder, isso significa que echo receberá 3 argumentos: "echo" , "-name" e "'*.txt'" .
Naturalmente, o mesmo se aplica ao comando find .
Você deseja que o comando find receba os argumentos -name e *.txt , portanto é necessário ajustar seu operador split + glob .
Você precisa do valor de $IFS para corresponder ao separador que você usa em $cond . Então, por exemplo:
cond='-name:*.txt'
IFS=':'
E você não quer a parte glob do operador split + glob , então você precisa desativá-lo com:
set -f
Então se torna:
cond='-name:*.txt'
IFS=:; set -f
find . $cond -ls
Ou você poderia fazer:
cond='-name *.txt'
set -f
find . $cond -ls
e assuma que $IFS não tenha sido modificado de seu valor padrão.
Alternativamente, se o seu shell suporta arrays, você pode querer usar isso em vez de confiar em variáveis escalares e esperar que o shell o divida na expansão.
Isso funcionaria com ksh93 , mksh , bash ou zsh :
cond=(-name '*.txt') # an array with two elements: "-name" and "*.txt"
find . "${cond[@]}" -ls # elements of the array expanded as separate arguments
# to find.