Come posso utilizzare una pipe nel parametro exec per un comando find?
Domanda
Sto cercando di costruire un comando find per elaborare un gruppo di file in una directory utilizzando due diversi eseguibili.Purtroppo, -exec
su find non consente di utilizzare pipe o addirittura \|
perché la shell interpreta prima quel carattere.
Ecco nello specifico cosa sto cercando di fare (che non funziona perché pipe termina il comando find):
find /path/to/jpgs -type f -exec jhead -v {} | grep 123 \; -print
Soluzione
Prova questo
find /path/to/jpgs -type f -exec sh -c 'jhead -v {} | grep 123' \; -print
In alternativa potresti provare a incorporare la tua istruzione exec all'interno di uno script sh e poi fare:
find -exec some_script {} \;
Altri suggerimenti
Un approccio leggermente diverso sarebbe usare xargs:
find /path/to/jpgs -type f -print0 | xargs -0 jhead -v | grep 123
che ho sempre trovato un po' più facile da capire e da adattare (gli argomenti -print0 e -0 sono necessari per gestire nomi di file contenenti spazi vuoti)
Questo Potrebbe (non testato) sarà più efficace dell'uso di -exec perché convoglierà l'elenco dei file a xargs e xargs si assicurerà che la riga di comando di jhead non diventi troppo lunga.
Con -exec
puoi eseguire solo un singolo eseguibile con alcuni argomenti, non comandi shell arbitrari.Per aggirare questo problema, è possibile utilizzare sh -c '<shell command>'
.
Tieni presente che l'uso di -exec
è abbastanza inefficiente.Per ogni file trovato, il comando deve essere eseguito nuovamente.Sarebbe più efficiente se potessi evitarlo.(Ad esempio, spostando il grep
fuori da -exec
o trasmettere i risultati di find
A xargs
come suggerito da Palmino.)
Utilizzando find
Il comando per questo tipo di attività forse non è l'alternativa migliore.Utilizzo frequentemente il seguente comando per trovare file che contengono le informazioni richieste:
for i in dist/*.jar; do echo ">> $i"; jar -tf "$i" | grep BeanException; done
Dato che questo produce un elenco, non dovresti:
find /path/to/jpgs -type f -exec jhead -v {} \; | grep 123
O
find /path/to/jpgs -type f -print -exec jhead -v {} \; | grep 123
Metti il tuo grep sui risultati di find -exec.
C'è un altro modo in cui puoi farlo, ma è anche piuttosto ghetto.
Usando l'opzione della shell extquote puoi fare qualcosa di simile a questo per trovare materiale exec e poi collegarlo a sh.
root@ifrit findtest # find -type f -exec echo ls $"|" cat \;|sh
filename
root@ifrit findtest # find -type f -exec echo ls $"|" cat $"|" xargs cat\;|sh
h
Ho solo pensato di aggiungerlo perché almeno per come l'ho visualizzato, era più vicino alla domanda originale dell'OP sull'uso delle pipe all'interno di exec.