find -exec: aggiunge argomenti tra {} e +
Voglio usare trova per individuare i file, quindi copiarli in una directory, quindi ho provato:
find . -name '*.png' -exec cp {} /tmp/dest +
Tuttavia, questo non riesce con
find: missing argument to `-exec'
Quando sostituisco +con a ;funziona, ma invoca cp per ogni file individualmente. Come posso aggiungere un argomento finale (come una directory di destinazione) quando si utilizza la +forma di -exec?
Ovviamente, in questo caso posso aggirare l'apparente limitazione usando cp -t(come indicato in questo post su Stack Overflow , ma quella soluzione è specifica per cp. Invece, potrei usare rsync, scp o qualche altro strumento. un modo generale per aggiungere argomenti tra {}e +in find -exec?
Risposte
No, se stai usando -exec ... {} +, potrebbe non esserci nulla tra {}e +oltre agli spazi bianchi. Non c'è modo di aggirarlo.
Dalla specifica standard POSIX del il findcomando :
-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +La fine dell'espressione primaria deve essere punteggiata da a
<semicolon>o da a<plus-sign>. Solo un<plus-sign>che segue immediatamente un argomento contenente solo i due caratteri{}punteggia la fine dell'espressione primaria. Altri usi del<plus-sign>non devono essere trattati come speciali.
Potrebbe essere una soluzione più generica
find ... -exec sh -c 'cp "$@" /tmp/dest' sh {} +
Qui, uno sh -cscript inline viene eseguito con batch di argomenti da find. All'interno dello script inline, "$@"ci sarà l'elenco degli argomenti passati (quotati individualmente), che ci permette di posizionarli come vogliamo sulla cpriga di comando.
Questo ci permette di usare non GNU cp(ad esempio su macOS o altri sistemi BSD, dove non ci sono -topzioni) o qualsiasi altra utility in cui si potrebbe voler aggiungere altri argomenti alla fine dell'elenco dei nomi di percorso provenienti da find.
Relazionato:
- Comprensione dell'opzione -exec di `find`
Nessuno lo ha chiesto, ma comunque ...
Con la directory di destinazione in una variabile, destdir:
destdir=/tmp/dest
find ... -exec sh -c 'destdir=$1; shift; cp "$@" "$destdir"' sh "$destdir" {} +
Notare che la destdirchiamata nella shell findè una variabile separata dalla destdirnello sh -cscript.
Oppure, con bash:
destdir=/tmp/dest
find ... -exec bash -c 'cp "${@:2}" "$1"' bash "$destdir" {} +
Questo significa "affettare" l' "$@"elenco per riorganizzarlo in modo appropriato per la cpriga di comando, senza estrarre $1il percorso della directory di destinazione, in una variabile separata.