Eu escrevi um find
comando 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 -print
opcionalmente, 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 eval
ser avaliado como código shell! Pode ser difícil de usar eval
com 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 find
foi \;
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.