Uniksowy „grep” dla łańcucha we wszystkich plikach gzip we wszystkich podkatalogach

8

Jak grep rekursywnie ciąg znaków przez wszystkie .gzpliki we wszystkich katalogach i podkatalogach?

Peter Mortensen
źródło

Odpowiedzi:

13

@ Steve Weet jest już prawie na miejscu. Użycie / dev / null jako dodatkowego argumentu jest dobrym sposobem na wymuszenie wyświetlenia nazwy pliku (pamiętam to, dzięki Steve), ale nadal uruchamia on exec dla każdego znalezionego pliku - ogromne obciążenie.

Chcesz uruchamiać zgrep tak rzadko, jak to możliwe, aby jak najlepiej wykorzystać każde wykonanie:

find . -iname '*.gz' -print0 | xargs -0 zgrep PATTERN

xargsdostarczy tyle argumentów (nazw plików), ile to możliwe, aby zgrep i wielokrotnie go wykonywał, dopóki nie użyje wszystkich plików dostarczonych przez findpolecenie. Użycie opcji -print0i -0pozwala mu działać, jeśli w nazwach plików lub katalogów są spacje.

W Mac OS X możesz osiągnąć ten sam efekt bez xargs:

find . -iname '*.gz' -exec zgrep PATTERN {} +
Stephen P.
źródło
+1 To naprawdę miłe. Nie zdawałem sobie sprawy, że xargs przeszedł więcej niż jeden argument. Wiele z moich * nix linii poleceń ma 20 lat i nie sądzę, że xargs zrobił to 20 lat temu.
Steve Weet
Okazuje się, że find na os / x zachowuje się tak samo jak xargs
Steve Weet
1
Zobacz mój komentarz do odpowiedzi Steve'a Weeta odnośnie końcówki „+” do -exec.
Daniel Andersson
Użyj, -Haby zawsze wyświetlać nazwę pliku z pasującą linią, przynajmniej w GNU grep.
Daniel Andersson
1
$ zgrep --help
Usage: /bin/zgrep [OPTION]... [-e] PATTERN [FILE]...
Look for instances of PATTERN in the input FILEs, using their
uncompressed contents if they are compressed.

Coś w stylu

find . -iname "*.gz" -exec zgrep PATTERN {} \
aioobe
źródło
-Exec odrodzi nową instancję zgrep dla każdego iterowanego pliku, uniemożliwiając zobaczenie nazwy pliku. Lepiej byłoby użyć zgrep -rdo przejścia przez drzewo lub jeśli -r nie działa, xargs zgrep
potokuj wyniki
Wchodzę /bin/zgrep: -r: option not supportedna mój nowo zainstalowany system Ubuntu.
aioobe
Zamiast tego możesz użyć xargs.
Noufal Ibrahim
Zobacz mój komentarz do odpowiedzi Steve'a Weeta odnośnie końcówki „+” do -exec.
Daniel Andersson
1

@ aioobe jest już prawie na miejscu. Polecenie wykona zadanie, ale nie poda nazwy pliku

Poniższe informacje powinny również zawierać nazwę pliku:

find . -iname "*.gz" -exec zgrep PATTERN {} /dev/null \;

Dodanie /dev/nullspowoduje, że zgrep zobaczy dwa nazwy plików, więc wyświetli nazwę pliku, jeśli znajdzie ciąg

EDYTOWAĆ

Dalsze badania ujawniają, że dla mojej maszyny (OS / X) -execargument znajdujący doda jak najwięcej nazw plików (podobnie jak xargszachowuje się).

Steve Weet
źródło
To całkiem fajne, nie wiedziałem o OSX -exec- chodzi mi o przenośność, więc nie używałbym jej w skrypcie, ale świetnie nadaje się do wiersza poleceń.
W przypadku innych wersji find, używając „+” zamiast „\;” aby zakończyć instrukcja exec będzie działała tak samo jak OSX, w przypadku wątków w tym wątku domyślnie tak jest. Zobacz ręczny wpis „-exec command {} +”. Nie dotyczy to wszystkich wersji find, ale większości współczesnych (np. W dystrybucjach opartych na Debianie).
Daniel Andersson
Użyj, -Haby zawsze wyświetlać nazwę pliku z pasującą linią, przynajmniej w GNU grep, zamiast /dev/nullhacka.
Daniel Andersson
0

Poniżej działa uczta w zsh

for archive in **/*.gz; do
    echo "[${archive}] "
    gzip -dc ${archive} | grep -n "String"
done

Może również pracować bash, kshitd ...

Johnsyweb
źródło