Estou tentando construir um -name
primário composto para o find
comando a partir de um número arbitrário de strings em uma matriz, no formato \( -name ${a[0]} -or -name ${a[1]} -or -name ${a[2]} ... \)
. Embora a digitação explícita do nome principal no terminal funcione, armazená-lo em uma variável e recuperá-lo por expansão de parâmetro não funciona. Como a expansão ocorrerá antes find
das execuções, presumo que o problema tenha algo a ver com a citação da variável expandida.
Abaixo está um exemplo mínimo para n=2 nomes, digitados literalmente ou recuperados de uma variável. Embora eu perceba que eu poderia canalizar para grep
, eu preferiria fazer tudo com find
neste caso.
$ ls
a1 a2 b1 b2 c1 c2
$ find . \( -name a\* -or -name b\* \)
./a1
./a2
./b1
./b2
$ names="\( -name a\* -or -name b\* \)"
$ printf "%s\n" "$names"
\( -name a\* -or -name b\* \)
$ find . $(printf "%q" "$names")
find: -name\: unknown primary or operator
$ find . $(printf "%s" "$names")
find: \): unknown primary or operator
$ find . $names
find: \): unknown primary or operator
$ find . "$names"
find: \( -name a\* -or -name b\* \): No such file or directory
Cada
-name
, cada-or
, cada parêntese e cada padrão deve ser um argumento separado parafind
. Não concatene os argumentos com espaços entre eles: você não pode voltar de lá para uma lista de argumentos — como você poderia saber quais espaços existem para separar argumentos e quais espaços fazem parte de um argumento? Veja também Por que meu script de shell engasga com espaços em branco ou outros caracteres especiais?Se seu shell suporta arrays (ksh, bash, zsh), armazene a lista de argumentos em um array.
Se seu shell não suporta arrays, você pode construir a lista nos argumentos posicionais (os argumentos que você pode acessar como
$1
,$2
, …). A limitação óbvia é que você não pode usar os argumentos posicionais para outro propósito.