Sto facendo un find
e quindi ottenere un elenco di file. Come posso collegarlo a un'altra utility come cat
(in modo che cat mostri il contenuto di tutti quei file) e fondamentalmente abbia bisogno di grep
qualcosa da questi file.
Sto facendo un find
e quindi ottenere un elenco di file. Come posso collegarlo a un'altra utility come cat
(in modo che cat mostri il contenuto di tutti quei file) e fondamentalmente abbia bisogno di grep
qualcosa da questi file.
Risposte:
Piping su un altro processo (anche se questo NON riuscirà a realizzare ciò che hai detto che stai cercando di fare):
command1 | command2
Questo invierà l'output di command1 come input di command2
-exec
su un find
(questo farà quello che vuoi fare - ma è specifico per find
)
find . -name '*.foo' -exec cat {} \;
(Tutto tra find
e -exec
sono i predicati find che stavi già utilizzando. {}
Sostituirà il particolare file che hai trovato nel comando ( cat {}
in questo caso); \;
è quello di terminare il -exec
comando.)
invia l'output di un processo come argomento della riga di comando a un altro processo
command2 `command1`
per esempio:
cat `find . -name '*.foo' -print`
(Nota che questi sono BACK-QUOTES non virgolette regolari (sotto la tilde ~ sulla mia tastiera).) Questo invierà l'output di command1
in command2
come argomenti della riga di comando. Tuttavia, i nomi dei file contenenti spazi (newline, ecc.) Verranno suddivisi in argomenti separati.
find
consentono di scrivere:, find . -name '*.foo' -exec cat {} +
dove +
indica che find
dovrebbero raggruppare tutti i nomi di file più convenienti in un'unica chiamata di comando. Questo è abbastanza utile (si occupa di spazi ecc. Nei nomi dei file senza ricorrere a -print0
e xargs -0
).
find . -name '*.foo' | xargs cat
find . -name '*.foo' | xargs cat | grep string
POSIX 2008 ha aggiunto il +
marcatore a find
cui ora raggruppa automaticamente tutti i file ragionevoli in un'unica esecuzione di comando, proprio come xargs
fa, ma con una serie di vantaggi:
Il problema del nome file è un problema con xargs
senza l' -0
opzione e il problema "esegui anche con zero nomi file" è un problema con o senza l' -0
opzione - ma GNU xargs
ha il -r
o--no-run-if-empty
opzione per impedire che ciò accada. Inoltre, questa notazione riduce il numero di processi, non che tu possa misurare la differenza nelle prestazioni. Quindi, potresti scrivere sensatamente:
find . -exec grep something {} +
find . -print | xargs grep something
Se sei su Linux o hai GNU find
e xargs
comandi, usa -print0
con find
e -0
conxargs
per gestire i nomi dei file contenenti spazi e altri caratteri dispari.
find . -print0 | xargs -0 grep something
grep
Se non desideri i nomi dei file (solo il testo), aggiungi un'opzione appropriata a grep
(di solito -h
per sopprimere le "intestazioni"). Per garantire assolutamente che il nome del file sia stampato da grep
(anche se viene trovato un solo file o all'ultima chiamata di grep
viene assegnato solo 1 nome file), quindi aggiungere/dev/null
alla xargs
riga di comando, in modo che ci siano sempre almeno due nomi di file.
xargs grep something
.
find
viene reindirizzato all'input standard di xargs
. Il xargs
programma legge l'input standard, suddividendo l'input su uno spazio bianco (spazi vuoti, newline, tab, ecc.) E aggiunge un numero di parole al comando grep something
ed esegue la riga di comando. xargs
quindi continua a leggere l'input e ad eseguire i comandi finché non si esaurisce l'input. xargs
esegue il grep
comando tutte le volte che è necessario per l'input fornito (da find
questo esempio).
/dev/null
perdere i messaggi di errore.
Esistono alcuni modi per passare l'elenco dei file restituiti dal find
comando al cat
comando, sebbene tecnicamente non tutti utilizzino il piping e nessuno effettivamente esegua il pipe direttamente cat
.
Il più semplice è usare i backtick ( `
):
cat `find [whatever]`
Questo prende l'output di find
e lo posiziona efficacemente sulla riga di comando di cat
. Questo non funziona bene se find
ha un output eccessivo (più di quello che può stare su una riga di comando) o se l'output ha caratteri speciali (come gli spazi).
In alcune shell, incluso bash
, si possono usare al $()
posto dei backtick:
cat $(find [whatever])
Questo è meno portatile, ma è annidabile. A parte questo, ha praticamente le stesse avvertenze dei backtick.
Poiché l'esecuzione di altri comandi su ciò che è stato trovato è un uso comune per find
, find ha -exec
un'azione che esegue un comando per ogni file che trova:
find [whatever] -exec cat {} \;
Il {}
è un segnaposto per il nome del file, e le \;
segna la fine del comando (è possibile avere altre azioni dopo -exec
.)
Questo verrà eseguito cat
una volta per ogni singolo file anziché eseguire una singola istanza di cat
passare più nomi di file che può essere inefficiente e potrebbe non avere il comportamento desiderato per alcuni comandi (anche se va bene cat
). Anche la sintassi è una cosa scomoda da digitare: è necessario sfuggire al punto e virgola perché il punto e virgola è speciale per la shell!
Alcune versioni di find
(in particolare la versione GNU) consentono di sostituire ;
con +
un uso -exec
'accodamento s per eseguire un minor numero di casi di cat
:
find [whatever] -exec cat {} +
Questo passerà più nomi di file a ogni invocazione di cat
, che può essere più efficiente.
Si noti che ciò non garantisce l'utilizzo di una singola chiamata. Se la riga di comando fosse troppo lunga, gli argomenti vengono suddivisi su più invocazioni di cat
. Per cat
questo probabilmente non è un grosso problema, ma per alcuni altri comandi questo può cambiare il comportamento in modi indesiderati. Sui sistemi Linux, il limite di lunghezza della riga di comando è piuttosto elevato, quindi la suddivisione in più invocazioni è piuttosto rara rispetto ad altri sistemi operativi.
L'approccio classico / portatile consiste nell'utilizzare xargs
:
find [whatever] | xargs cat
xargs
esegue il comando specificato ( cat
, in questo caso) e aggiunge argomenti in base a ciò che legge da stdin. Proprio come -exec
con +
, questo interromperà la riga di comando, se necessario. Cioè, se find
produce troppo output, verrà eseguito cat
più volte. Come menzionato nella sezione -exec
precedente, ci sono alcuni comandi in cui questa suddivisione può comportare comportamenti diversi. Si noti che l'utilizzo in xargs
questo modo ha problemi con gli spazi nei nomi dei file, in quanto xargs
utilizza solo gli spazi bianchi come delimitatore.
Il metodo più robusto, portatile ed efficiente utilizza anche xargs
:
find [whatever] -print0 | xargs -0 cat
Il -print0
flag dice find
di usare \0
delimitatori (carattere null) tra i nomi di file e il -0
flag dice xargs
di aspettarsi questi \0
delimitatori. Questo ha un comportamento praticamente identico all'approccio -exec
... +
, sebbene sia più portatile (ma sfortunatamente più prolisso).
ls
.
$()
Funziona anche con comandi diversi da find
.
Mi sembra un lavoro per uno script di shell:
for file in 'find -name *.xml'
do
grep 'hello' file
done
o qualcosa di simile
Il comando find ha un argomento -exec che puoi usare per cose come questa, puoi semplicemente fare il grep direttamente usando quello.
Ad esempio ( da qui, altri buoni esempi in questa pagina ):
find . -exec grep "www.athabasca" '{}' \; -print
In bash, sarebbe appropriato:
find /dir -type f -print0 | xargs -0i cat {} | grep whatever
Questo troverà tutti i file nella /dir
directory e inoltrerà in modo sicuro i nomi dei file xargs
, che guideranno in sicurezzagrep
.
Saltare xargs
non è una buona idea se hai molte migliaia di file /dir
; cat
si interromperà a causa dell'eccessiva lunghezza dell'elenco degli argomenti.xargs
risolverà tutto per te.
L' -print0
argomento da find
associare -0
all'argomento xargs
per gestire correttamente i nomi di file con spazi. L' -i
argomento per xargs
consentire di inserire il nome file dove richiesto nella cat
riga di comando. Le parentesi vengono sostituite dal nome file reindirizzato nel cat
comando da find
.
Questo funziona per me
find _CACHE_* | while read line; do
cat "$line" | grep "something"
done
Usa ggrep .
ggrep -H -R -I "mysearchstring" *
per cercare un file in unix contenente testo situato nella directory corrente o in una sottodirectory
Questo stamperà ricorsivamente il nome e il contenuto dei soli file.
find . -type f -printf '\n\n%p:\n' -exec cat {} \;
Modifica (versione migliorata): questo stamperà ricorsivamente il nome e il contenuto dei file di testo (ascii).
find . -type f -exec grep -Iq . {} \; -print | xargs awk 'FNR==1{print FILENAME ":" $0; }'
Un altro tentativo
find . -type f -exec grep -Iq . {} \; -printf "\n%p:" -exec cat {} \;
Stai cercando di trovare testo nei file? Puoi semplicemente usare grep per quello ...
grep searchterm *
Per elencare e vedere i contenuti di tutti i file abc.def su un server nelle directory / ghi e / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec ls {} \; -exec cat {} \;
Per elencare i file abc.def che hanno voci commentate e visualizzate, vedere quelle voci nelle directory / ghi e / jkl
find /ghi /jkl -type f -name abc.def 2> /dev/null -exec grep -H ^# {} \;
find -name '*.foo' -print
funzionato benissimo per me ... Grazie