error al ejecutar el comando buscar usando variable

error al ejecutar el comando buscar usando variable

He escrito un findcomando para copiar algunos archivos fuente:

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

Esto funciona bien, pero también quiero agregar el final -printopcionalmente, así que hago algo como esto:

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}
}

Pero sucede que falla con un error:

find: missing argument to `-exec'

No sé por qué falla y agradecería cualquier consejo. ¡Gracias de antemano!

Respuesta1

Utilice una matriz y ejecútela como argumentos para un comando simple.

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[@]}"
}

O una cadena y evaluarla 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"
}

Tenga en cuenta que en el código anterior, es importante asegurarse de que ${args[destdir]}no esté expandido en el momento de la asignación, de lo contrario, su contenido se pasaría para evalevaluarlo como código shell. Puede ser difícil usarlo evalde manera segura, yo optaría por el enfoque de matriz, especialmente considerando que ya estás usando matrices asociativas.

En su enfoque, estaba utilizando el operador split+glob en su cadena para crear los argumentos de un comando simple. Eso no funcionó porque el último argumento findfue \;en lugar de just ;(y también tendrías problemas con las comillas literales pasadas a find). Podrías usar el 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
}

Pero eso significa que no funcionará si ${args[destdir]}contiene caracteres de espacio. Siempre puedes reemplazar esos espacios con un carácter que sea menos probable que aparezca en ${args[destdir]}me gusta :o en una nueva línea.

información relacionada