Jak grepować tysiące plików w katalogu dla setek ciągów w pliku

11

Próbuję skomponować grepoświadczenie, które mnie zabija. Jestem też zmęczony otrzymywaniem arguments list too longbłędu. Mam plik, nazwijmy go subset.txt. Zawiera setki linii z określonymi ciągami, takimi jak MO43312948. W moim katalogu obiektowym mam tysiące plików i muszę skopiować wszystkie pliki zawierające łańcuchy wymienione w subset.txtinnym katalogu.

Próbowałem zacząć od tego, aby po prostu zwrócić pasujące pliki z katalogu obiektów.

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

Ciągle pojawia się `bash: / bin / grep: Lista argumentów za długa``

Revlis
źródło
6
Dlaczego wprowadziłeś "$(subset.txt)"takie polecenie? To jest podstawianie poleceń , które spowoduje, że twoja powłoka zostanie wykonana subset.txt (tak jakby to była komenda lub skrypt).
JigglyNaga

Odpowiedzi:

23

Można przekazać katalog jako cel do grepz -Roraz pliku wzorców wejściowych z -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.

Więc szukasz:

grep -Ff subset.txt -r objects/

Możesz uzyskać listę pasujących plików za pomocą:

grep -Flf subset.txt -r objects/

Jeśli więc twoja ostateczna lista nie jest zbyt długa, możesz po prostu:

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

Jeśli to zwróci argument list too longbłąd, użyj:

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

A jeśli twoje nazwy plików mogą zawierać spacje lub inne dziwne znaki, użyj (zakładając GNU grep):

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

Wreszcie, jeśli chcesz wykluczyć pliki binarne, użyj:

grep -IFZlf subset.txt -r objects/ | xargs -0I{} mv {} bar/
terdon
źródło
… Lub w celu uniknięcia potencjalnie tysięcy mvwywołań z jednym argumentem: ... | xargs -0 mv -t bar/(zakładając, że mvobsługuje tę -topcję).
David Foerster,
11

posługiwać się

grep -F -f subset.txt 

powiedzieć grepowi, żeby czytał z subset.txtpliku.

możesz użyć polecenia find do przejścia pliku.

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

lub

find . -type f -exec grep -F -f subset.txt {}  +
Archemar
źródło
Czy jest jakaś korzyść z używania findzamiast -rinnych niż dodatkowe filtrowanie?
phk
1
@phk grep -rwyszukuje dowiązania symboliczne do zwykłych plików, które mogą, ale nie muszą być pożądane (jeśli wskazują w tym samym drzewie, przeszukujesz ten sam plik dwa razy; jeśli wskazują na zewnątrz, przeszukujesz plik, który może, ale nie musi, być być pożądanym).
Gilles „SO- przestań być zły”
Nowoczesne wersje grepmają opcje kontrolowania ich interakcji z dowiązaniami symbolicznymi (w man grepcelu określenia specyfiki bieżącego systemu). Rekursywne grepbędzie znacznie szybsze niż uruchamianie greppojedynczo dla każdego pliku za pośrednictwem find.
Perry
1
@Perry jesteś tego pewien? Dlaczego? Zauważ też, że ta odpowiedź jest używana -exec +, więc grupuje pliki i nie uruchamia jednego grep na plik.
terdon
Poprawiłem się, nie zdawałem sobie sprawy z różnej semantyki -exec {} +vs -exec {} \;... każdego dnia uczysz się czegoś nowego (wciąż nie widzę powodu, dla którego pojedynczy rekurencyjny grepnie byłby szybszy niż wielokrotny grepbieg z findpowodu tworzenia procesów i analizowania wzorców, ale ja nie mam pod ręką konkretnych numerów, aby to zrobić).
Perry
3

Jeśli chcesz jeszcze bardziej przyspieszyć grep, możesz ustawić ustawienia narodowe w swojej powłoce przed jej uruchomieniem, tzn. Użyj „LC_ALL = c”. Zostanie to odziedziczone do grep i wyłączy przetwarzanie Unicode, gdy nie będzie to konieczne, aw niektórych przypadkach może znacznie przyspieszyć grep. Świetny blog dokumentujący to można znaleźć na stronie http://www.inmotionhosting.com/support/website/ssh/speed-up-grep-searches-with-lc-all . Ta sztuczka może także przyspieszyć skrypty powłoki bash, nie tylko grep.

Erik Brandsberg
źródło