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.