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

536

Jak znaleźć pliki w bieżącym katalogu, które nie zawierają słowa foo(za pomocą grep)?

Senthil Kumar
źródło

Odpowiedzi:

818

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

$ grep -L "foo" *
ghostdog74
źródło
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
Andy Lester
źródło
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
Adrian
źródło
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
Senthil Kumar
źródło
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"
użytkownik999305
źródło
9

Będziesz potrzebować:

find .  -not  -ipath '.*svn*' -exec  grep  -H -E -o -c  "foo"  {} \; | grep :0\$
Forrest Tiffany
źródło
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”.

Jasio
źródło
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
Gruffy
źródło
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
Zak
źródło
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 ">"
    
użytkownik6305682
źródło
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.

zandeep
źródło
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
dfri
źródło
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
JMD
źródło
-4
grep -irnw "filepath" -ve "pattern"

lub

grep -ve "pattern" < file

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

Sójka
źródło
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"
walkerlin
źródło
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