Ich habe einen find
Befehl zum Kopieren einiger Quelldateien geschrieben:
find ./lib ./tools -type f -regex '.*\.\(cpp\|c\|h\)$' -exec cp --parents \{\} /tmp/potato \; -print
Das funktioniert gut, aber ich möchte das Trailing -print
optional hinzufügen, also mache ich so etwas:
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}
}
Es tritt jedoch ein Fehler auf:
find: missing argument to `-exec'
Ich weiß nicht, warum es fehlschlägt und wäre für jeden Rat dankbar. Vielen Dank im Voraus!
Antwort1
Verwenden Sie entweder ein Array und führen Sie es als Argumente für einen einfachen Befehl aus.
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[@]}"
}
Oder einen String und werte ihn als Shellcode aus:
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"
}
Beachten Sie, dass im obigen Code darauf geachtet werden muss, dass ${args[destdir]}
zum Zeitpunkt der Zuweisung nicht erweitert wird, da sonst sein Inhalt eval
zur Auswertung als Shell-Code übergeben würde! Die sichere Verwendung kann schwierig sein eval
. Ich würde den Array-Ansatz wählen, insbesondere wenn Sie bereits assoziative Arrays verwenden.
In Ihrem Ansatz haben Sie den Operator split+glob auf Ihren String angewendet, um die Argumente eines einfachen Befehls zu erstellen. Das hat nicht funktioniert, weil das letzte Argument to statt just find
war (und Sie hätten auch Probleme mit den wörtlichen Anführungszeichen, die an übergeben wurden ). Sie könnten den Operator split+glob wie folgt verwenden:\;
;
find
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
}
Das bedeutet aber, dass es nicht funktioniert, wenn ${args[destdir]}
es Leerzeichen enthält. Sie können diese Leerzeichen immer durch ein Zeichen ersetzen, das weniger wahrscheinlich in ${args[destdir]}
Zeilenumbrüchen vorkommt :
.