Domanda

Voglio trovare un comando bash che mi permetta di grep ogni file in una directory e scrivere l'output di quel grep in un file separato. La mia ipotesi sarebbe stata quella di fare qualcosa di simile

ls -1 | xargs -I{} "grep ABC '{}' > '{}'.out"

, ma, per quanto ne so, xargs non piace il doppi apici. Se rimuovo i doppi apici, invece, il comando reindirizza l'output di tutto il comando per un singolo file chiamato '{}'. Fuori invece di una serie di singoli file.

Qualcuno sa di un modo per farlo utilizzando xargs? Ho appena usato questo scenario grep come un esempio per illustrare il mio problema con xargs così eventuali soluzioni che non utilizzano xargs non sono applicabili per me.

È stato utile?

Soluzione

Non fare l'errore di fare questo:

sh -c "grep ABC {} > {}.out"

Questa si romperà sotto un sacco di condizioni, tra cui i nomi dei file funky ed è impossibile citare destra. Il tuo {} deve essere sempre un singolo argomento completamente separato al comando per evitare code bug di iniezione. Quello che dovete fare, è questo:

xargs -I{} sh -c 'grep ABC "$1" > "$1.out"' -- {}

Si applica a xargs così come find.

A proposito, non usare mai xargs senza l'-0 opzione (se non per una sola volta l'uso interattivo molto raro e controllato in cui non si è preoccupato per la distruzione dei dati).

Inoltre, non analizzare ls. Mai. Utilizzare globbing o <=> invece: http://mywiki.wooledge.org/ParsingLs

Utilizzare <=> per tutto ciò che ha bisogno di ricorsione e un ciclo semplice con un glob per tutto il resto:

find /foo -exec sh -c 'grep "$1" > "$1.out"' -- {} \;

o non ricorsivo:

for file in *; do grep "$file" > "$file.out"; done

Si noti l'uso corretto delle citazioni.

Altri suggerimenti

Una soluzione senza xargs è la seguente:

find . -mindepth 1 -maxdepth 1 -type f -exec sh -c "grep ABC '{}' > '{}.out'" \;

... e lo stesso può essere fatto con <=>, si scopre:

ls -1 | xargs -I {} sh -c "grep ABC '{}' > '{}.out'"

Modifica : virgolette singole aggiunti dopo un'osservazione di lhunath .

Presumo vostro esempio è solo un esempio e che potrebbe essere necessario> per altre cose. GNU http://www.gnu.org/software/parallel/ potrebbe essere in vostro soccorso . Non ha bisogno di ulteriore citando il più a lungo i nomi dei file non contengono \ n:

ls | parallel "grep ABC {} > {}.out"

Se si dispone di nomi di file con \ n in esso:

find . -print0 | parallel -0 "grep ABC {} > {}.out"

Come bonus aggiuntivo che si ottiene i lavori eseguiti in parallelo.

Modifica.

È possibile installare GNU parallelo semplicemente:

wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel

Guarda i video intro per saperne di più: http://pi.dk/1

10 secondi di installazione:

wget pi.dk/3 -qO - | sh -x
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top