Risposte:
Il compito di interpretare il simbolo pipe come istruzione per eseguire più processi e reindirizzare l'output di un processo all'input di un altro processo è responsabilità della shell (/ bin / sh o equivalente).
Nel tuo esempio puoi scegliere di utilizzare la shell di livello superiore per eseguire le tubazioni in questo modo:
find -name 'file_*' -follow -type f -exec zcat {} \; | agrep -dEOE 'grep'
In termini di efficienza, questo risultato costa una chiamata di find, numerose chiamate di zcat e una chiamata di agrep.
Ciò comporterebbe la generazione di un solo processo agrep che elaborerebbe tutto l'output prodotto da numerose invocazioni di zcat.
Se per qualche motivo desideri invocare più volte, puoi fare:
find . -name 'file_*' -follow -type f \
-printf "zcat %p | agrep -dEOE 'grep'\n" | sh
Questo costruisce un elenco di comandi che utilizzano i pipe per eseguire, quindi li invia a una nuova shell per essere effettivamente eseguiti. (L'omissione dell'ultimo "| sh" è un buon modo per eseguire il debug o eseguire serie di righe di comando a secco come questa.)
In termini di efficienza, questo risultato costa una invocazione di find, una invocazione di sh, numerose invocazioni di zcat e numerose invocazioni di agrep.
La soluzione più efficiente in termini di numero di invocazioni di comandi è il suggerimento di Paul Tomblin:
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
... che costa una invocazione di find, una invocazione di xargs, alcune invocazioni di zcat e una invocazione di agrep.
-exec sh -c "… | … " \;
.
la soluzione è semplice: eseguire tramite sh
... -exec sh -c "zcat {} | agrep -dEOE 'grep' " \;
-c
opzione. Altrimenti riceverai un No such file or directory
messaggio di errore sconcertante .
find -type f -name '*.mdds' -exec sh -c "echo {} | sed -e 's/_[0-9]\+//g' | xargs mv {}" \;
find . -name "file_*" -follow -type f -print0 | xargs -0 zcat | agrep -dEOE 'grep'
È inoltre possibile reindirizzare a un while
ciclo che può eseguire più azioni sul file che find
individua. Quindi eccone uno per cercare negli jar
archivi un dato file di classe java nella cartella con una grande distribuzione di jar
file
find /usr/lib/eclipse/plugins -type f -name \*.jar | while read jar; do echo $jar; jar tf $jar | fgrep IObservableList ; done
il punto chiave è che il while
ciclo contiene più comandi che fanno riferimento al nome del file passato separato da punto e virgola e questi comandi possono includere pipe. Quindi, in questo esempio, faccio eco al nome del file corrispondente, quindi elenco ciò che è nel filtro di archivio per un determinato nome di classe. L'output è simile a:
/usr/lib/eclipse/plugins/org.eclipse.core.contenttype.source_3.4.1.R35x_v20090826-0451.jar /usr/lib/eclipse/plugins/org.eclipse.core.databinding.observable_1.2.0.M20090902-0800 .jar org / eclipse / core / databinding / osservable / list / IObservableList .class /usr/lib/eclipse/plugins/org.eclipse.search.source_3.5.1.r351_v20090708-0800.jar / usr / lib / eclipse / plugins / org.eclipse.jdt.apt.core.source_3.3.202.R35x_v20091130-2300.jar /usr/lib/eclipse/plugins/org.eclipse.cvs.source_1.0.400.v201002111343.jar / usr / lib / eclipse / plugins / org.eclipse.help.appserver_3.1.400.v20090429_1800.jar
nella mia shell bash (xubuntu10.04 / xfce) rende davvero grassetto il nome di classe abbinato mentre fgrep
evidenzia la stringa abbinata; questo rende veramente facile scansionare l'elenco di centinaia di jar
file che sono stati cercati e vedere facilmente eventuali corrispondenze.
su windows puoi fare la stessa cosa con:
for /R %j in (*.jar) do @echo %j & @jar tf %j | findstr IObservableList
nota che in Windows il comando separator è '&' not ';' e che '@' sopprime l'eco del comando per fornire un output ordinato proprio come linux trova l'output sopra; sebbene findstr
non sia in grassetto la stringa abbinata, quindi devi guardare un po 'più vicino all'output per vedere il nome della classe corrispondente. Si scopre che il comando 'for' di Windows conosce parecchi trucchi come scorrere ciclicamente i file di testo ...
godere
Ho scoperto che l'esecuzione di un comando shell shell (sh -c) funziona meglio, ad esempio:
find -name 'file_*' -follow -type f -exec bash -c "zcat \"{}\" | agrep -dEOE 'grep'" \;
Se stai cercando una semplice alternativa, puoi farlo usando un ciclo:
for i in $(find -name 'file_*' -follow -type f);do zcat $i | agrep -dEOE 'grep');done
o, forma più generale e di facile comprensione:
for i in $(YOUR_FIND_COMMAND);do YOUR_EXEC_COMMAND_AND_PIPES );done
e sostituisci {} con $ i in YOUR_EXEC_COMMAND_AND_PIPES