Come funziona questo comando find usando "find ... -exec sh -c '...' sh {} +"?


8

@StephaneChazelas ha pubblicato la seguente soluzione a questa domanda e risposta: Problemi con l'utilizzo di "find -exec {} +" .

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

Cosa sta succedendo esattamente qui? In particolare cosa fa l'ultimo sh {}? Sembra che sia lì solo per pacificare il -execcomando find in modo che abbia qualcosa da fare, un NOOP.

Potrei metterlo altrettanto facilmente echo {}e sembra funzionare bene.

Risposte:


9

La sintassi è:

find ... -exec cmd {} +

findtroverà un numero di file basato sui criteri ...e verrà eseguito cmdcon quell'elenco di percorsi di file come argomenti, il maggior numero possibile senza superare il limite della dimensione degli argomenti con un comando.

Se necessario, può dividere l'elenco dei file e chiamare cmdpiù volte. Ad esempio, potrebbe finire per chiamare:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

Un limite è che {}deve essere l'ultimo. Ad esempio non puoi scrivere:

find ... -exec cmd {} other args +

come puoi con ';'invece di '+'.

Tu puoi scrivere:

find ... -exec echo foo {} +

ma no:

find ... -exec echo {} foo +

Quindi, se è necessario aggiungere alcuni argomenti aggiuntivi cmddopo l'elenco dei file, è necessario ricorrere alla chiamata di una shell. (Altri motivi per cui è necessario chiamare una shell potrebbero essere ogni volta che è necessario utilizzare una funzione di shell come reindirizzamenti, pipe, alcune espansioni di stringhe ....)

In sh -c 'inline-script' x a b c, poiché inline-script, $0è x, $1è a, $2è b... così "$@"è l'elenco di questi 3 argomenti: a, bec. Quindi in:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

Per lo script inline , $0(che viene utilizzato ad esempio quando si visualizzano messaggi di errore) è impostato su find-shed "$@"è l'elenco dei file (ciò che si findespande {}in).

Utilizzando lo execspeciale built-in della shell:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

Diciamo alla shell di non eseguire un processo aggiuntivo da eseguire cmd, ma invece di eseguirlo nello stesso processo (sostituendo il processo di esecuzione della shell con quel comando). Alcune conchiglie come bash, zshe alcune implementazioni di kshfarlo implicitamente per l'ultimo comando in uno script.


Potresti usare una subshell invece di exec lì? -exec sh -c '(cmd1; cmd2;)' find-sh {} +?
slm

Quindi, se ti capisco correttamente, ci find-sh {}sono argomenti per il comando sh -c '...', giusto?
slm

@slm, findchiamerà /bin/shcon come argomenti ("sh", "-c", "...", "find-sh", "./file1", "./file2"...). And inside ... , that maps (the shells maps that) to $ 0` essere "find-sh", ed i parametri posizionali ( $1, $2... che si potrebbe dire che sono gli argomenti al script inline ) essendo ./file1, ./file2.
Stéphane Chazelas,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.