erro ao executar o comando find usando variável

erro ao executar o comando find usando variável

Eu escrevi um findcomando para copiar alguns arquivos de origem:

find ./lib ./tools -type f -regex '.*\.\(cpp\|c\|h\)$' -exec cp --parents \{\} /tmp/potato \; -print

Isso funciona bem, mas também quero adicionar o final -printopcionalmente, então faço algo assim:

function deploy_source_code {
    exec_cmd="find ./lib ./tools -type f -regex '.*\.\(cpp\|c\|h\)$' -exec cp --parents \{\} ${args[destdir]} \;"
    if [ "${args[verbose]}" = "true" ]; then
        exec_cmd="${exec_cmd} -print"
    fi  
    ${exec_cmd}
}

Mas acontece que falha com erro:

find: missing argument to `-exec'

Não sei por que falha e agradeceria qualquer conselho. Desde já, obrigado!

Responder1

Use um array e execute-o como argumento para um comando simples.

deploy_source_code() {
  exec_cmd=(find ./lib ./tools -type f -regex '.*\.\(cpp\|c\|h\)$' 
    -exec cp --parents {} "${args[destdir]}" \;)
  if [ "${args[verbose]}" = "true" ]; then
    exec_cmd+=(-print)
  fi  
  "${exec_cmd[@]}"
}

Ou uma string e avalie-a como código shell:

deploy_source_code() {
  exec_cmd="find ./lib ./tools -type f -regex '.*\.\(cpp\|c\|h\)$' \
    -exec cp --parents {} \"\${args[destdir]}\" \;"
  if [ "${args[verbose]}" = "true" ]; then
    exec_cmd+=" -print"
  fi  
  eval "$exec_cmd"
}

Observe que no código acima, é importante garantir que ${args[destdir]}não seja expandido no momento da atribuição, caso contrário, seu conteúdo seria passado para evalser avaliado como código shell! Pode ser difícil de usar evalcom segurança, eu usaria a abordagem de array, especialmente considerando que você já está usando arrays associativos.

Na sua abordagem, você estava usando o operador split+glob em sua string para criar os argumentos de um comando simples. Isso não funcionou porque o último argumento to findfoi \;em vez de just ;(e você também teria problemas com aspas literais passadas para find). Você poderia usar o operador split+glob como:

deploy_source_code() {
  exec_cmd="find ./lib ./tools -type f -regex .*\.\(cpp\|c\|h\)$ \
    -exec cp --parents {} ${args[destdir]} ;"
  if [ "${args[verbose]}" = "true" ]; then
    exec_cmd+=" -print"
  fi
  IFS=" " # split on space
  set -f  # disable glob
  $exec_cmd # invoke the split+glob operator
}

Mas isso significa que não funcionará se ${args[destdir]}contiver caracteres de espaço. Você sempre pode substituir esses espaços por um caractere com menor probabilidade de ocorrer em ${args[destdir]}like :ou nova linha.

informação relacionada