2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

Jak zignorować pewne nazwy plików używając "find"?

Jedną z moich ulubionych komend BASH jest:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

, które przeszukuje zawartość wszystkich plików w bieżącym katalogu i pod nim dla podanego SearchString. Jako programista, przydało się to nieraz.

Ze względu na mój obecny projekt i strukturę mojej bazy kodów, chciałbym jednak uczynić to polecenie BASH jeszcze bardziej zaawansowanym, nie przeszukując żadnych plików, które są w lub pod katalogiem, który zawiera “.svn”, ani żadnych plików, które kończą się na “.html”

Strona MAN dla find trochę mnie zmyliła. Próbowałem użyć -prune, i to dało mi dziwne zachowanie. W próbie pominięcia tylko stron .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 być może brakuje mi sensu działania opcji -prune. Czy moglibyście mi pomóc?

Dzięki

Odpowiedzi (3)

209
209
209
2012-03-06 00:40:37 +0000

Możesz użyć funkcji negacji (!) find, aby nie dopasowywać plików o określonych nazwach:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Więc jeśli nazwa kończy się na .html lub zawiera .svn gdziekolwiek w ścieżce, nie będzie pasować, a więc exec nie zostanie wykonany.

12
12
12
2012-03-06 13:54:15 +0000

Mam ten sam problem od dłuższego czasu i istnieje kilka rozwiązań, które mogą mieć zastosowanie w różnych sytuacjach:

  • ack-grep jest rodzajem “deweloperskiego grep”, który domyślnie pomija katalogi kontroli wersji i pliki tymczasowe. Strona man wyjaśnia, jak wyszukiwać tylko określone typy plików i jak zdefiniować własne . Własne opcje grep i --exclude programu
  • --exclude-dir mogą być bardzo łatwo użyte do pomijania globów plików i pojedynczych katalogów (niestety nie ma globbingu dla katalogów).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... powinno działać, ale powyższe opcje są prawdopodobnie mniej kłopotliwe na dłuższą metę.
9
9
9
2012-03-06 03:29:21 +0000

Następujące polecenie find usuwa katalogi, których nazwy zawierają .svn, Mimo że nie schodzi do katalogu, wypisywana jest przycięta nazwa ścieżki …(-name '*.svn' jest przyczyną!) …

Możesz odfiltrować nazwy katalogów przez: grep -d skip który cicho pomija takie wejściowe “nazwy katalogów”.

Z GNU grep, możesz użyć -H zamiast /dev/null. Jako drobny problem uboczny: może być znacznie szybszy niż `\;`, np. dla 1 miliona jednolinijkowych plików, używając `\;` zajęło to _4m20s_, używając zajęło to tylko 1.2s.

Poniższa metoda używa xargs zamiast -exec, i zakłada, że nie ma nowych linii \n w żadnej z twoich nazw plików. Użyte tutaj, xargs jest takie samo jak “ w metodzie find.

xargs może przepuszczać nazwy plików zawierające kolejne spacje, zmieniając ogranicznik wejściowy na '\n' z opcją -d.

Wyklucza to katalogi, których nazwy zawierają .svn i grepsuje tylko pliki, które nie kończą się na .html.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'