Come eseguire il grep di migliaia di file in una directory per centinaia di stringhe in un file


11

Sto cercando di comporre una grepdichiarazione e mi sta uccidendo. Sono anche stanco di ottenere l' arguments list too longerrore. Ho un file, chiamiamolo subset.txt. Contiene centinaia di linee con stringhe specifiche come MO43312948. Nella mia directory degli oggetti ho migliaia di file e devo copiare tutti i file che contengono le stringhe elencate subset.txtin un'altra directory.

Stavo cercando di iniziare con questo per restituire i file corrispondenti dalla directory degli oggetti.

grep -F "$(subset.txt)" /objects/*

Continuo a ricevere `bash: / bin / grep: lista degli argomenti troppo lunga``


6
Perché hai inserito "$(subset.txt)"il comando in quel modo? Cioè la sostituzione di comando , che renderà la vostra shell eseguire subset.txt (come se si trattasse di un comando o uno script).
JigglyNaga,

Risposte:


23

È possibile passare una directory come destinazione a grepcon -Re un file di schemi di input con -f:

  -f FILE, --file=FILE
          Obtain patterns from FILE, one per line.  If this option is used
          multiple  times  or  is  combined with the -e (--regexp) option,
          search for all patterns given.  The  empty  file  contains  zero
          patterns, and therefore matches nothing.

   -R, --dereference-recursive
          Read all files under each directory,  recursively.   Follow  all
          symbolic links, unlike -r.

Quindi stai cercando:

grep -Ff subset.txt -r objects/

Puoi ottenere l'elenco dei file corrispondenti con:

grep -Flf subset.txt -r objects/

Quindi, se l'elenco finale non è troppo lungo, puoi semplicemente fare:

 mv $(grep -Flf subset.txt -r objects/) new_dir/

Se restituisce un argument list too longerrore, utilizzare:

grep -Flf subset.txt -r objects/ | xargs -I{} mv {} bar/

E se i nomi dei tuoi file possono contenere spazi o altri strani caratteri, usa (supponendo GNU grep):

grep -FZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

Infine, se si desidera escludere i file binari, utilizzare:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/

... o per evitare potenzialmente migliaia di mvinvocazioni con un argomento ciascuno: ... | xargs -0 mv -t bar/(supponendo che tu mvsupporti l' -topzione).
David Foerster,

11

uso

grep -F -f subset.txt 

per dire a grep di leggere dal subset.txtfile.

puoi usare find per camminare sul file.

find . -type f -exec grep -F -f subset.txt {} \;

o

find . -type f -exec grep -F -f subset.txt {}  +

Qualche vantaggio nell'utilizzare findinvece -rche nel fare un filtro aggiuntivo?
phk,

1
@phk grep -rcerca nei collegamenti simbolici a file regolari, che possono essere o meno desiderabili (se puntano all'interno dello stesso albero, stai cercando lo stesso file due volte; se puntano all'esterno, stai cercando un file che può o meno essere desiderato).
Gilles 'SO- smetti di essere malvagio' il

Le versioni moderne di grephanno opzioni per controllare la loro interazione con collegamenti simbolici ( man grepper determinare le specifiche per il sistema attuale). Un ricorsivo grepsarà molto più veloce rispetto all'esecuzione grepindividuale su ogni file tramite find.
Perry,

1
@Perry ne sei sicuro? Perché? Inoltre, nota che questa risposta sta usando -exec +, quindi raggrupperà i file e non eseguirà un grep per file.
terdon

Sono corretto, non ero a conoscenza della diversa semantica di -exec {} +vs -exec {} \;... impari qualcosa di nuovo ogni giorno (non vedo ancora alcun motivo per cui un singolo ricorsivo grepnon sarà più veloce di più greps a findcausa della creazione del processo e dell'analisi dei modelli in testa ma io non hai numeri specifici da consegnare per eseguire il backup).
Perry,

3

Se vuoi velocizzare ancora di più grep, puoi impostare la locale nella tua shell prima di eseguirla, cioè usa "LC_ALL = c". Questo sarà ereditato in grep e disabiliterà l'elaborazione Unicode quando non è necessario e in alcuni casi può velocizzare notevolmente grep. Un ottimo blog che documenta questo può essere trovato su http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Questo trucco può anche velocizzare gli script della shell bash, non solo grep.

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.