Jak znaleźć pliki, które nie zawierają danego wzorca ciągu?


Odpowiedzi:


818

Jeśli twój grep ma opcję -L(lub --files-without-match):

$ grep -L "foo" *

1
Jak wskazano w innym miejscu ack pomaga domyślnie unikać plików .svn (subversion).
GuruM,

11
@GuruM Można to zrobić w GNU grep, eksportując zmienną GREP_OPTIONS='--exclude-dir=.svn --exclude-dir=.git': ^)
bufh

6
Lub odpowiednik przy użyciu ag :ag -L 'foo'
biskup

5
Działa jak magia! Wskazówka: użyj -rLzamiast, -Laby dopasować podkatalogi
Ufos

1
@ Larry - Bardziej czystym sposobem na uniknięcie problemów z globowaniem jest użycie opcji „pustej” długiej w następujący sposób: grep -L 'foo' -- *Standardowo polecenia wymagające długich opcji --wskazują, że po tym punkcie nie ma już żadnych opcji.
Paddy Landau

45

Spójrz na ack. Robi .svnwykluczenia dla Ciebie automatycznie, daje Perl wyrażeń regularnych, i jest prosty do pobrania z jednego programu Perl.

Odpowiednikiem tego, czego szukasz, powinno być ack:

ack -L foo

23

Możesz to zrobić tylko z grep (bez znalezienia).

grep -riL "foo" .

To jest wyjaśnienie zastosowanych parametrów grep

     -L, --files-without-match
             each file processed.
     -R, -r, --recursive
             Recursively search subdirectories listed.

     -i, --ignore-case
             Perform case insensitive matching.

Jeśli użyjesz l(małe litery) otrzymasz odwrotnie (pliki z dopasowaniami)

     -l, --files-with-matches
             Only the names of files containing selected lines are written

17

Następujące polecenie daje mi wszystkie pliki, które nie zawierają wzorca foo:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep 0

4
Chcesz zmienić grep 0 na końcu na grep 0 $ (w przeciwnym razie otrzymujesz błędne dopasowania dla plików, które mają znak 0 w nazwie pliku).
clouseau,

9
@clouseau ma w większości rację ... Jednak grep '0$'pasowałoby też do plików z wielokrotnością 10 linii! Na grep ':0$'końcu musisz sprawdzić wyraźne „: 0” na końcu linii. Otrzymasz wtedy tylko pliki z dopasowanymi zerami linii.
TrinitronX,

System UNIX, na którym pracuję, nie miał wersji find ani grep z tymi opcjami, więc musiałem użyć polecenia „ack” sugerowanego w innych komentarzach.
KC Baltz,

14

Następujące polecenie wyklucza potrzebę wyszukiwania przez filtrowanie svnfolderów za pomocą drugiego grep.

grep -rL "foo" ./* | grep -v "\.svn"

9

Będziesz potrzebować:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep :0\$

6

Miałem szczęście

grep -H -E -o -c "foo" */*/*.ext | grep ext:0

Moje próby z grep -vpo prostu dały mi wszystkie linie bez „foo”.


4

Problem

Muszę przefakturować duży projekt, który używa .phtmlplików do pisania HTML przy użyciu wbudowanego kodu PHP. Chcę zamiast tego użyć szablonów wąsów . Chcę znaleźć wszelkie .phtmlgiles, które nie zawierają łańcucha, new Mustacheponieważ nadal wymagają przepisania.

Rozwiązanie

find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

Wyjaśnienie

Przed rurami:

Odnaleźć

find . Znajdź pliki rekurencyjnie, zaczynając od tego katalogu

-iname '*.phtml'Nazwa pliku musi zawierać .phtml(i czyni to bez rozróżniania wielkości liter)

-exec 'grep -H -E -o -c 'new Mustache' {}'Uruchom greppolecenie na każdej ze zgodnych ścieżek

Grep

-H Zawsze drukuj nagłówki plików z wierszami wyjściowymi.

-E Interpretuj wzorzec jako rozszerzone wyrażenie regularne (tj. Wymuś, aby grep zachowywał się jak egrep).

-o Drukuje tylko pasującą część linii.

-c Tylko liczba wybranych wierszy jest zapisywana na standardowe wyjście.


To da mi listę wszystkich ścieżek plików kończących się na .phtml, wraz z liczbą przypadków, w których łańcuch new Mustachewystępuje w każdej z nich.

$> find . -iname '*.phtml$' -exec 'grep -H -E -o -c 'new Mustache' {}'\;

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/orders.phtml:1
./app/MyApp/Customer/View/Account/banking.phtml:1
./app/MyApp/Customer/View/Account/applycomplete.phtml:1
./app/MyApp/Customer/View/Account/catalogue.phtml:1
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

Pierwsza rura grep :0$filtruje tę listę, aby uwzględnić tylko linie kończące się na :0:

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml:0
./app/MyApp/Customer/View/Account/studio.phtml:0
./app/MyApp/Customer/View/Account/classadd.phtml:0
./app/MyApp/Customer/View/Account/orders-trade.phtml:0

Druga rura sed 's/..$//'usuwa ostatnie dwa znaki każdego wiersza, pozostawiając tylko ścieżki plików.

$> find . -iname '*.phtml' -exec grep -H -E -o -c 'new Mustache' {} \; | grep :0$ | sed 's/..$//'

./app/MyApp/Customer/View/Account/quickcodemanagestore.phtml
./app/MyApp/Customer/View/Account/studio.phtml
./app/MyApp/Customer/View/Account/classadd.phtml
./app/MyApp/Customer/View/Account/orders-trade.phtml

3

Jeśli używasz git, przeszukuje wszystkie śledzone pliki:

git grep -L "foo"

i możesz wyszukiwać w podzbiorze śledzonych plików, jeśli masz włączone ** globowanie podkatalogów ** ( shopt -s globstarw .bashrc, patrz to ):

git grep -L "foo" -- **/*.cpp

1

Mój grep nie ma żadnej opcji -L. Znalazłem obejście, aby to osiągnąć.

Pomysły to:

  1. aby zrzucić całą nazwę pliku zawierającego zasłużony ciąg do pliku txt1.txt.
  2. zrzuć całą nazwę pliku z katalogu do pliku txt2.txt.
  3. zrób różnicę między plikiem 2 zrzutu za pomocą polecenia diff.

    grep 'foo' *.log | cut -c1-14 | uniq > txt1.txt
    grep * *.log | cut -c1-14 | uniq > txt2.txt
    diff txt1.txt txt2.txt | grep ">"
    

Zapominam polecenia, ale zamiast zrzucać nazwy plików, możesz faktycznie zrobić diffpomiędzy dwoma strumieniami wyjściowymi (myślę, że otaczasz polecenia nawiasami, a gdzieś tam jest też nawias kątowy), jeśli twój system to obsługuje, tak myślę jest pytanie, ponieważ nie obsługujegrep -L
Dexygen

1

find *20161109* -mtime -2|grep -vwE "(TRIGGER)"

Możesz określić filtr pod „find”, a ciąg wykluczenia pod „grep -vwE”. Jeśli chcesz filtrować według zmodyfikowanego czasu, użyj mtime w find.


To wydaje się pokazywać mi wszystkie wiersze bez ciągu, OP prosi tylko o nazwy plików.
Ben Farmer

1

Otwórz raport o błędzie

Jak skomentował @tukan, istnieje otwarty raport o błędzie dla Ag dotyczący flagi -L/ --files-without-matches:

Ponieważ postęp w zgłaszaniu błędów jest niewielki, nie należy polegać na-L opcji wymienionej poniżej , dopóki błąd nie zostanie rozwiązany. Zamiast tego użyj różnych podejść przedstawionych w tym wątku. Cytując komentarz do raportu o błędzie [moje podkreślenie]:

Wszelkie aktualizacje na ten temat? -Lcałkowicie ignoruje dopasowania w pierwszym wierszu pliku. Wygląda na to, że jeśli nie zostanie to wkrótce naprawione, flaga powinna zostać całkowicie usunięta, ponieważ w rzeczywistości nie działa tak, jak reklamowano .


Silver Searcher - Ag (zamierzona funkcja - patrz raport o błędach)

Jako potężną alternatywę grepmożesz użyć Srebrnego Poszukiwacza - Ag :

Narzędzie do wyszukiwania kodu podobne do ack z naciskiem na szybkość.

Patrząc na man ag, znajdujemy opcję -Llub --files-without-matches:

...

OPTIONS
    ...

    -L --files-without-matches
           Only print the names of files that don´t contain matches.

To znaczy, aby rekurencyjnie wyszukiwać pliki, które nie pasują foo, z bieżącego katalogu:

ag -L foo

Aby przeszukać tylko bieżący katalog w poszukiwaniu plików, które nie pasują foo, po prostu określ --depth=0rekurencję:

ag -L foo --depth 0

Od czasu do czasu nie udaje się to z powodu -Lbłędu - github.com/ggreer/the_silver_searcher/issues/238
tukan

@ tukan dzięki za podpowiedź. Zaktualizowałem odpowiedź; decyduje się nie usuwać odpowiedzi, ale zamiast tego otwiera się z informacją o błędzie.
dfri

1

kolejna alternatywa, gdy grep nie ma opcji -L (na przykład IBM AIX), tylko grep i powłoka:

for file in * ; do grep -q 'my_pattern' $file || echo $file ; done

-4
grep -irnw "filepath" -ve "pattern"

lub

grep -ve "pattern" < file

powyższe polecenie da nam wynik, ponieważ -v znajdzie odwrotność przeszukiwanego wzorca


1
Spowoduje to wydrukowanie linii, które nie zawierają wzoru. Możesz dodać -lopcję drukowania tylko nazwy pliku; ale nadal drukuje nazwy każdego pliku zawierającego dowolny wiersz, który nie zawiera wzorca. Wierzę, że OP chce znaleźć pliki, które nie zawierają żadnej linii zawierającej wzorzec.
tripleee

Podane polecenie wyświetla listę plików w „ścieżce plików” wraz ze wszystkimi wierszami, które nie zawierają „wzorca”.
aprodan

-6

Poniższe polecenie może pomóc w filtrowaniu wierszy zawierających podciąg „foo”.

cat file | grep -v "foo"

2
Wyświetla linie, które nie pasują, a nie nazwy plików, które nie zawierają dopasowania w żadnej linii. Aby dodać obrażenia do obrażeń, jest to bezużyteczne użyciecat .
tripleee
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.