Chcę znaleźć pliki zawierające dwa ciągi razem, na przykład plik zawiera oba string1
i string2
.
Chcę pełną ścieżkę plików wyjściowych. Nie chcę widzieć ostrzeżeń „odmowa zgody”.
grep -l string2 `grep -l string1 /path/*`
który jest taki sam jak
grep -l string2 $(grep -l string1 /path/*)
Edycja: oto dlaczego grep string1 /path/* | grep string2
nie robi tego, co myślę, że chce alwbtc.
$ cd /tmp
$ cat a
apples
oranges
bananas
$ cat b
apples
mangoes
lemons
$ cat c
mangoes
limes
pears
$ cd ~
$ grep apples /tmp/* | grep mangoes
$
Nic nie znaleziono, ale plik b zawiera oba ciągi.
Oto, co myślę, że chce alwbtc
$ grep -l apples $(grep -l mangoes /tmp/*)
/tmp/b
-l
opcji zwracania nazw plików zamiast wierszy. Następnie używa znaku dolara lub cudzysłowu, aby przekazać tę listę jakoFILE
argument do drugiego grepa. To pozwala drugiemu grepowi przeszukać cały każdy znaleziony plik zamiast poszczególnych linii, jak w moim rozwiązaniu.-l
opcję, aby oba polecenia były uważane za równe.Rurociąg jeden
grep
do drugiego:grep "string1" /path/to/files/* | grep "string2"
źródło
Oto odpowiednik ackpolecenie do odpowiedzi RedGrittyBrick :
Działa w ten sam sposób (z wyjątkiem
ack
domyślnie przeszukuje bieżący katalog rekurencyjnie). Treść w$()
wyszukiwaniu,string1
ale-l
wyświetla tylko nazwy plików, w których znaleziono ten ciąg. Są one następnie przekazywane jako argumenty do polecenia zewnętrznego, co oznacza, żestring2
jest wyszukiwane tylko na tej liście plików.źródło
lub mniej zbędnie:
Działa to, jeśli ciągi znaków znajdują się w różnych wierszach tego samego pliku, a także pozwala uniknąć fałszywych alarmów, jeśli nazwa pliku zawiera jeden z ciągów.
źródło
Aby rozwinąć rozwiązanie @ RedGrittyBrick, które ma wadę podczas uruchamiania polecenia nienadzorowanego plus, aby ukryć wyjście błędów zgodnie z przeznaczeniem i znaleźć rekurencyjnie pliki, które można rozważyć
grep -l 'STRING1' $(! grep -lrs 'STRING2' /absolute/path/to/search/dir && echo /dev/null)
-s
opcja tłumi komunikaty o błędach-r
opcja pozwala na wyszukiwanie ciągów w dowolnie zagnieżdżonych katalogach w!
połączeniu z&& echo /dev/null
gwarancją, że polecenie się nie rozłączy. W przeciwnym razie, jeśliinner grep
nie znajdzie żadnego pliku, nie wypisze niczego, więcouter grep
będzie czekać w nieskończoność na wyszukiwanie. To rozwiązanie wyjścia/dev/null
w tych przypadkach takouter grep
będzie szukaćSTRING1
w/dev/null
którym to miało nie znalezienie czegokolwiek.źródło
Szukałem rozszerzalnego sposobu na wykonanie 2 lub więcej ciągów i wymyśliłem to:
Pierwszy grep rekursywnie wyszukuje nazwy plików zawierających
string1
wewnątrzpath-to-files
.Wyniki są przesyłane strumieniowo, do
xargs
którego uruchamiane jest jedno lub więcej poleceń grep dla tych plikówstring2
.Wyniki są następnie przesyłane do innego
xargs
polecenia dlastring3
- jest to to samo, co pierwszexargs
wywołanie, ale szuka innego ciągu.Użycie opcji
xargs
pozwoli uniknąć problemów w przypadku tak wielu wyników, że wynikowa linia poleceń wynikająca z użycia tyknięć zwrotnych jest zbyt długa.Aby uniknąć ostrzeżeń, możemy przekierować
stderr
na/dev/null
:Nie jest potrzebny przy kolejnych wywołaniach grep, ponieważ
string1
został już znaleziony w pliku, więc uprawnienia są znane.źródło