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.