Jednym z moich ulubionych poleceń BASH jest:
find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;
który przeszukuje zawartość wszystkich plików znajdujących się w bieżącym katalogu i poniżej pod kątem określonego SearchString. Jako programista czasami się przydał.
Ze względu na mój obecny projekt i strukturę bazy kodu chciałbym jednak uczynić to polecenie BASH jeszcze bardziej zaawansowanym, nie wyszukując żadnych plików, które znajdują się w lub poniżej katalogu zawierającego „.svn”, ani żadnych plików, które zakończ na „.html”
Jednak strona MAN dla wyszukiwania trochę mnie zdezorientowała. Próbowałem użyć -prune, co dało mi dziwne zachowanie. Próbując pominąć tylko strony .html (na początek), próbowałem:
find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;
i nie uzyskałem zachowania, na które liczyłem. Wydaje mi się, że brakuje mi punktu -pune. Czy moglibyście mi pomóc?
Dzięki
find
nie jest wbudowanym poleceniem bash, ale osobnym programemgrep -rl 'SearchString'
find
do wyszukiwania w pliku.-name '*.*'
nie znajduje wszystkich plików: tylko te z.
imieniem (użycie*.*
zwykle jest DOS-ism, podczas gdy w Uniksie zwykle używasz tylko*
do tego). Aby naprawdę dopasować je wszystkie, po prostu usunąć całkowicie argument:find . -exec ...
. Lub jeśli chcesz zastosować grep tylko do plików (i pominąć katalogi), to zróbfind . -type f -exec ...
.Odpowiedzi:
Możesz użyć funkcji negowania (!) Znajdowania, aby nie dopasowywać plików o określonych nazwach:
Więc jeśli nazwa kończy się na .html lub zawiera .svn w dowolnym miejscu na ścieżce, nie będzie pasować, a więc exec nie zostanie wykonany.
źródło
*.*
celem było dopasowanie tylko plików zawierających.
? Find dopasuje wszystkie pliki w przypadku brakuname
dyrektywy, więc powyższe dopasuje wszystko oprócz html i svn-wholename '*.svn*'
raczej chcesz-name
..svn
katalogi zostały wykluczone z wyników wyszukiwania.! -name '.'
powinien wykluczyć.
z wyników wyszukiwania.Od dawna mam ten sam problem i istnieje kilka rozwiązań, które można zastosować w różnych sytuacjach:
ack-grep
jest rodzajem „programistygrep
”, który domyślnie pomija katalogi kontroli wersji i pliki tymczasowe.man
Strona wyjaśnia jak szukać tylko określonych typów plików i jak definiować własne .grep
Własne--exclude
i--exclude-dir
opcje mogą być bardzo łatwo użyte do pominięcia globów plików i pojedynczych katalogów (niestety globowania dla katalogów).find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ...
powinien działać, ale powyższe opcje są prawdopodobnie mniej kłopotliwe na dłuższą metę.źródło
Poniższe
find
polecenie wykonuje katalogi przycinania, których nazwy zawierają..svn
Chociaż nie schodzi ono do katalogu, nazwa przycinanej ścieżki jest drukowana ... (-name '*.svn'
jest przyczyną!) ..Możesz odfiltrować nazwy katalogów poprzez
grep -d skip
:, które cicho pomijają takie wejściowe „nazwy katalogów”.Z GNU grep możesz używać
-H
zamiast/dev/null
. Jako drobny problem uboczny:\+
może być znacznie szybszy niż\;
np. na 1 milion plików jednowierszowych , użycie\;
zajęło 4m20s , użycie\+
zajęło tylko 1,2s .Następująca metoda używa
xargs
zamiast-exec
i zakłada, że nie ma żadnych znaków nowej linii\n
w żadnej z nazw plików . Stosowane tutajxargs
jest bardzo podobne do znaleziska\+
.xargs
może przekazywać nazwy plików, które zawierają kolejne spacje, zmieniając ogranicznik wejściowy na'\n'
z-d
opcją.Wyklucza to katalogi, których nazwy zawierają
.svn
i grepują tylko te pliki, które się nie kończą.html
.źródło
\+
wariantu działania -exec. Brawo dla drobnych problemów ubocznych!+
nie jest to specjalny znak dla powłoki, nie musisz pisać\
przed nią.