Jak przekazać listę plików do grep

98

Używam findi otrzymuję listę plików, przez które chcę grepprzejść. Jak mogę potokować tę listę grep?

Arcabard
źródło

Odpowiedzi:

116

Cóż, ogólnym przypadkiem, który działa z dowolnym poleceniem zapisującym na standardowe wyjście, jest użycie xargs, które pozwoli ci dołączyć dowolną liczbę argumentów wiersza poleceń na końcu polecenia:

$ find … | xargs grep 'search'

Lub osadzić polecenie w greplinii za pomocą odwrotnych klawiszy lub $(), który uruchomi polecenie i zastąpi jego wynik:

$ grep 'search' $(find …)

Zauważ, że te polecenia nie działają, jeśli nazwy plików zawierają spacje lub niektóre inne „dziwne znaki” ( \'"dla xargs, \[*?dla $(find …)).


Jednak w konkretnym przypadku findmożliwości wykonania programu na danych argumentach jest wbudowany:

$ find … -exec grep 'search' {} \;

Wszystko pomiędzy -execi ;jest poleceniem do wykonania; {}zastępuje się nazwą pliku znalezioną przez find. Spowoduje to wykonanie osobnego grepdla każdego pliku; ponieważ grepmoże mieć wiele nazw i szukanie ich wszystkich, można zmienić ;, aby +powiedzieć znaleźć przejść wszystkie nazwy plików pasujące do grepnaraz:

$ find … -exec grep 'search' {} \+
Michał Mrożek
źródło
1
Należy zauważyć, że dwie pierwsze formy nie działają z nazwami plików zawierającymi spacje.
enzotib
1
Wolę find ... -type f -print0 | xargs -r0 grep 'search' /dev/null. CO BYŁO DO OKAZANIA. Chociaż -exec +jest bardzo wydajny, nie istnieje we wszystkich wersjach find.
Arcege
Niestety nie mogę 3 razy sprawdzić poprawności.
Arcabard
3
Sugeruję użycie -execraczej niż xargs. Jeśli użyjesz polecenia -execin find, utworzy on tylko jedną powłokę do grep dla zawartości. Jeśli użyjesz xargs, utworzy dwie powłoki: jedną dla drugiej, finda drugą dla xargs.
2
eksperymentalnie stwierdzam, że $ find … -exec grep 'search' {} \+forma jest znacznie najszybsza.
gogoud
9

Niektóre wersje grep(np. W niewbudowanym systemie Linux, BSD lub Mac OS X) mają -ropcję wyszukiwania rekurencyjnego. W OpenBSD użyj -R(i nie ma --excludejak w poniższym przykładzie). Obejmuje to proste kombinacje findz grep.

Jeśli twoja implementacja nie ma -Rflagi lub jeśli chcesz bardziej wyszukane kryteria dopasowywania plików, możesz użyć -execpodstawowego z, findaby ją wykonać grep. Kilka starszych findimplementacji nie obsługuje -exec+; w tych systemach użyj ;zamiast niego +(wywoła to grepraz na plik, więc będzie wolniejszy, ale w przeciwnym razie wynik będzie taki sam). Zwróć uwagę na /dev/nullsztuczkę, która powoduje grepwyświetlenie nazwy pliku, nawet jeśli jest wywoływana w jednym pliku (GNU grep i FreeBSD / NetBSD / OSX grep mają -Hopcję osiągnięcia tego samego efektu).

find . -type f -name '*.o' -prune -o -exec grep 'needle' /dev/null {} +
grep -r --exclude='*.o' 'needle' .
Gilles
źródło
2
GNU grepma -Hopcję, aby zawsze drukować nazwę pliku.
enzotib