erro ao executar o comando find usando a variável

1

Eu escrevi um comando find 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 eu também quero adicionar o -print à direita opcionalmente, então eu 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 a falha com erro:

find: missing argument to '-exec'

Eu não sei por que isso falha e eu gostaria de receber qualquer conselho. Obrigado antecipadamente!

    
por XNor 29.09.2016 / 14:44

1 resposta

2

Use uma matriz e execute-a como argumentos 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 será passado para eval para ser avaliado como código de shell! Pode ser difícil usar eval com segurança, eu iria com a abordagem de matriz, especialmente considerando que você já está usando matrizes de associação.

Em 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 para find foi \; em vez de apenas ; (e você também teria problemas com os caracteres de aspas literais passados 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]} , como : ou newline.

    
por 29.09.2016 / 15:05