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

Hoe kan ik bepaalde bestandsnamen negeren met "find"?

Een van mijn favoriete BASH commando’s is:

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

die de inhoud van alle bestanden in en onder de huidige directory doorzoekt op de opgegeven SearchString. Als ontwikkelaar is dit wel eens handig geweest.

Vanwege mijn huidige project, en de structuur van mijn codebase, zou ik dit BASH commando echter nog geavanceerder willen maken door geen bestanden te doorzoeken die in of onder een directory staan die “.svn” bevat, of bestanden die eindigen op “.html”

De MAN pagina voor find bracht me echter in verwarring. Ik probeerde -prune te gebruiken, en het gaf me vreemd gedrag. In een poging om alleen de .html pagina’s over te slaan (om te beginnen), probeerde ik :

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

en kreeg niet het gedrag waar ik op hoopte. Ik denk dat ik de bedoeling van -prune mis. Kunnen jullie me helpen?

Bedankt

Antwoorden (3)

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

Je kunt de negate (!) functie van find gebruiken om bestanden met specifieke namen niet te matchen:

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

Dus als de naam eindigt op .html of ergens in het pad .svn bevat, zal het niet matchen, en dus zal de exec niet worden uitgevoerd.

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

Ik heb dit probleem lange tijd gehad, en er zijn verschillende oplossingen die in verschillende situaties van toepassing kunnen zijn:

  • ack-grep is een soort “ontwikkelaar’s grep” die standaard versiebeheer mappen en tijdelijke bestanden overslaat. De man pagina legt uit hoe u alleen specifieke bestandstypen kunt doorzoeken en hoe u uw eigen kunt definiëren.
  • grep‘s eigen --exclude en --exclude-dir opties kunnen heel eenvoudig gebruikt worden om globs van bestanden en single directories over te slaan (geen globbing voor directories, helaas).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... zou moeten werken, maar de bovenstaande opties zijn op de lange duur waarschijnlijk minder lastig.
9
9
9
2012-03-06 03:29:21 +0000

Het volgende find commando snoeit de directory’s waarvan de naam bevat .svn, Hoewel het niet afdaalt in de directory, wordt de gesnoeide padnaam afgedrukt …(-name '*.svn' is de oorzaak!) …

U kunt de directorynamen wegfilteren via: grep -d skip die dergelijke ingevoerde “directorynamen” stilletjes overslaat.

Met GNU grep kun je -H gebruiken in plaats van /dev/null. Als kleine bijkomstigheid: kan veel sneller zijn dan `\;`, b.v. voor 1 miljoen eenregelige bestanden, met behulp van `\;` duurde het _4m20s_, met behulp van duurde het slechts 1.2s.

De volgende methode gebruikt xargs in plaats van -exec, en gaat er van uit dat er geen nieuwe regels \n in een van uw bestands namen zitten. Zoals hier gebruikt, is xargs ongeveer hetzelfde als “ van find.

xargs kan bestandsnamen passeren die opeenvolgende spaties bevatten door het invoerbegrenzingsteken te veranderen in '\n' met de -d optie.

Dit sluit mappen uit waarvan de naam _x6& bevat en greps alleen bestanden die niet eindigen op .svn.

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