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.