Ik heb dit veel gebruikt, de verbetering die ik probeer te bereiken is het vermijden van echobestandsnamen die niet overeenkwamen in grep. Betere manier om dit te doen?

 for file in `find . -name "*.py"`; do echo $file; grep something $file; done 

Reacties

Antwoord

 find . -name "*.py" -exec grep something {} \; -print  

zou de bestandsnaam na de overeenkomende regels afdrukken.

 find . -name "*.py" -exec grep something /dev/null {} +  

zou de bestandsnaam voor elke overeenkomende regel afdrukken (we voegen /dev/null toe voor het geval dat er slechts één overeenkomend bestand als grep drukt de bestandsnaam niet “af als er slechts één bestand is doorgegeven om in te kijken. De GNU-implementatie van grep heeft een -H optie daarvoor als alternatief).

 find . -name "*.py" -exec grep -l something {} +  

zou alleen de bestandsnamen afdrukken van de bestanden die ten minste één overeenkomende regel hebben.

Om de bestandsnaam vóór de overeenkomende regels af te drukken, kunt u awk gebruiken in plaats daarvan:

 find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +  

Of bel grep tweemaal voor elk bestand – hoewel dat “d minder efficiënt is omdat het ten minste één grep -opdracht zou uitvoeren en maximaal twee voor elk bestand (en de inhoud van het bestand tweemaal ):

 find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;  

In ieder geval je wilt de uitvoer van find op die manier niet doorlopen en vergeet niet je variabelen .

Als je een shell-loop wilde gebruiken, met GNU-tools:

 find . -name "*.py" -exec grep -l --null something {} + | xargs -r0 sh -c " for file do printf "%s\n" "$file" grep something < "$file" done" sh  

(werkt ook op FreeBSD en afgeleiden).

Antwoord

I Als je GNU grep gebruikt, kun je de optie -r of --recursive gebruiken om deze eenvoudige zoekopdracht voor je uit te voeren:

 grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match  

Je hebt alleen find nodig als dat nodig is meer geavanceerde predikaten.

Reacties

  • Afhankelijk van de versie van GNU grep, grep kan al dan niet in symlinks kijken of symlinks naar mappen doorlopen. Mogelijk vindt u ook enkele variaties in de verwerking van andere soorten niet-reguliere bestanden.

Antwoord

Jij kan grep vertellen om de bestandsnaam in de uitvoer op te nemen. Dus als er een match is, wordt deze op de console getoond; als er geen overeenkomst is in een bestand, wordt er geen regel voor dat bestand afgedrukt.

find . -name "*.py" | xargs grep -n -H something 

Van de man grep:

-H Always print filename headers with output lines -n, --line-number Each output line is preceded by its relative line number in the file, starting at line 1. The line number counter is reset for each file processed. This option is ignored if -c, -L, -l, or -q is specified. 

Als uw bestanden namen met spaties bevatten, moet u de pipe omwisselen om NUL-tekens als scheidingsteken te gebruiken. Het volledige commando ziet er nu als volgt uit:

find . -name "*.py" -print0 | xargs -0 grep -n -H something 

Antwoord

Je kunt probeer iets als:

find . -name "*.py:" -exec grep -l {} \; 

Dit exec grep-commando voor elk bestand, ontdekt door het find-commando en zijn standaard vind-commando-functie

Answer

Gebruik het -l argument.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done 

Een meer vindbaar gebruik zou zijn:

for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done 

Antwoord

Daar zijn grep alternatieven die hun resultaten standaard in het gewenste formaat uitvoeren. De twee meest populaire die ik ken zijn ag (ook bekend als “the silver searcher”) en ack. ag wordt geadverteerd als een sneller alternatief voor ack.

$ ag "^\w+\s*\w+\(" ~/build/i3/src build/i3/src/display_version.c 58:void display_running_version(void) { build/i3/src/load_layout.c 42:static TAILQ_HEAD(focus_mappings_head, focus_mapping) focus_mappings = 518:json_content_t json_determine_content(const char *filename) { 575:void tree_append_json(Con *con, const char *filename, char **errormsg) { build/i3/src/x.c 64:CIRCLEQ_HEAD(state_head, con_state) state_head = 67:CIRCLEQ_HEAD(old_state_head, con_state) old_state_head = 70:TAILQ_HEAD(initial_mapping_head, con_state) initial_mapping_head = 97:void x_con_init(Con *con, uint16_t depth) { ... 

Ik kan je hier niet laten zien, maar de uitvoer is netjes gekleurd. Ik krijg de bestandsnamen in olijfgroen, de regelnummers in goudgeel en het overeenkomende stuk in elke regel in bloedrood. De kleuren kunnen echter worden aangepast.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *