Jak mogę znaleźć wszystkie pliki, które NIE zawierają ciągu tekstowego?

40

Jakiego zwięzłego polecenia mogę użyć, aby znaleźć wszystkie pliki, które NIE zawierają ciągu tekstowego?

Próbowałem tego (używając -v do odwrócenia parametrów grep) bez powodzenia:

find . -exec grep -v -l shared.php {} \;

Ktoś powiedział, że to zadziała:

find . ! -exec grep -l shared.php {} \;

Ale wydaje mi się, że to nie działa.

Ta strona ma ten przykład:

find ./logs -size +1c  > t._tmp
while read filename
do
     grep -q "Process Complete" $filename
     if [ $? -ne 0 ] ; then
             echo $filename
     fi
done < t._tmp
rm -f t_tmp

Ale to uciążliwe i wcale nie zwięzłe.

ps: Wiem, że grep -L *to zrobi, ale jak mogę użyć polecenia find w połączeniu z grep do wykluczonych plików, to jest to, co naprawdę chcę wiedzieć.

pss: Również nie jestem pewien, jak grep zawiera podkatalogi ze grep -L *składnią, ale nadal chcę wiedzieć, jak go używać find:)

cwd
źródło
1
Pierwsze polecenie, które napisałeś, działało dobrze na moim komputerze. Jakiej wersji Find używasz? A skoro już to robimy, może określ, który system uniksowy używasz ..
rahmu
@rahmu, to polecenie prawie zawsze nie działa zgodnie z oczekiwaniami. Prawdopodobnie miałeś bardzo konkretny przypadek. Proszę zobaczyć unix.stackexchange.com/questions/339619/…
sgnsajgon

Odpowiedzi:

8
find . -type f | xargs grep -H -c 'shared.php' | grep 0$ | cut -d':' -f1    

LUB

find . -type f -exec grep -H -c 'shared.php' {} \; | grep 0$ | cut -d':' -f1

W tym przypadku obliczamy liczbę pasujących wierszy (za pomocą -c) w pliku, jeśli liczba wynosi 0, to jest to wymagany plik, więc wycinamy pierwszą kolumnę, tj. Nazwę pliku z wyniku.

Sachin Divekar
źródło
6
To jest strasznie skomplikowane. Zobacz odpowiedź Kevina .
Gilles „SO- przestań być zły”,
@Gilles tak Zgadzam się z tobą. Mam +1 jego odpowiedź.
Sachin Divekar
6
Jest to nie tylko „strasznie skomplikowane”, ale błędne, ponieważ zawierałoby także listę wszystkich plików zawierających wielokrotność 10 wierszy pasujących do wzorca. Nawet jeśli grepzostała ustalona ta nadal zakładamy żadnych nazw plików zawierających :lub nowej linii znaków ...
don_crissti
@don_crissti, dzięki za wzmiankę! Mimo to, chyba że użyjesz dużo kodu kopiuj-wklej, powyższe rozwiązanie jest bardzo fajnym chwytem.
Ufos
@Ufos - Naprawdę nie otrzymuję twojego komentarza ... To źle . W każdym razie, możesz go użyć, jeśli wygląda ci to na „naprawdę fajny chwyt” ...
don_crissti,
57

Znalezienie powinno działać, jeśli zmienisz -v -l(pliki, które nie pasują do żadnej linii) na -L(pliki bez pasujących linii), ale możesz również użyć opcji greprekursywnej ( -r):

grep -rL shared.php .
Kevin
źródło
które znalezisko powinno działać?
cwd 14.12.11
@Kevin - przepraszam find . -exec grep -v -l shared.php {} \;(i wszystkie inne warianty, które próbowałem) nie działa dla mnie. Jestem na OS X, ale nie sądzę, że to powinno mieć znaczenie. Dałem ci +1, ponieważ zapomniałem o tej -ropcji.
cwd
@cwd Wiem, że to jest stare, ale chcę to zostawić tutaj dla przyszłych czytelników: fakt, że jesteś na OS X, robi różnicę. Mac OSX używa poleceń FreeBSD. Większość ludzi tutaj przyjmuje polecenia w stylu Linux (GNU). Mają różne argumenty, różne sposoby obchodzenia się ze szczegółami.
Rich Homolka
Od 2016 roku OSX wydaje się wspierać-L
David Moles
@kevin Powiedziałem, że tak, nie że nie. :) nie żeby ktokolwiek wyraźnie powiedział, że tak nie jest, ale komentarze były mylące (i na pewno wpadłem na inne problemy z OS X / BSD vs. GNU).
David Moles,
4

Wiem, że grep -L *to zrobi, ale jak mogę użyć findpolecenia w połączeniu z, grepaby wykluczyć pliki, to jest to, co naprawdę chcę wiedzieć

Możesz użyć findi greppolubić to:

find . -type f ! -exec grep -q 'PATTERN' {} \; -print

Tutaj -printjest wykonywana tylko wtedy, gdy poprzedni wyraz: ! -exec ... {}ocenia jako true.
Tak więc dla każdego znalezionego pliku grep -q 'PATTERN'jest execużywany, jeśli wynik jest falsewtedy, całe wyrażenie jest ! -exec grep -q 'PATTERN'oceniane jako truei nazwa pliku jest printedytowana.

don_crissti
źródło
2
Ten ma tę zaletę, że jest standardowy i przenośny.
Stéphane Chazelas
Istnieje jednak różnica w stosunku do GNU grep -L, ponieważ będzie on zawierał również nieczytelne pliki na liście.
Stéphane Chazelas
1

Nie znaleziono pasującego wyniku według opcji -L

grep -iL shared.php .
prakash
źródło
-1

Myślę, że szukasz polecenia takiego jak

find . -type f -execdir grep -q -v shared.php {} \; -print

Opcji -qmarki grepzamknąć i po użyciu -execdirtrzeba -printdrukować odnaleziono plików.

Ronin Tom
źródło