Jeg brukte dette mye, forbedringen jeg prøver å oppnå er å unngå ekkofilnavn som ikke samsvarte med grep. Bedre måte å gjøre dette på?

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

Kommentarer

Svar

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

vil skrive ut filnavnet etter de samsvarende linjene.

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

vil skrive ut filnavnet foran hver samsvarende linje (vi legger til /dev/null for tilfellet der det bare er en samsvarende fil som grep skriver ikke ut filnavnet hvis den bare har sendt en fil å se i. GNU-implementeringen av grep har et alternativ -H for det som alternativ).

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

vil bare skrive ut filnavnene på filene som har minst en samsvarende linje.

Hvis du vil skrive ut filnavnet før de samsvarende linjene, kan du bruke awk i stedet:

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

Eller ring grep to ganger for hver fil – skjønt at «d er mindre effektiv da den vil kjøre minst en grep -kommando og opptil to for hver fil (og les innholdet i filen to ganger ):

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

I alle fall du vil ikke løpe over utdata fra find slik og husk å sitere variabler .

Hvis du vil bruke en shell-loop, med GNU-verktøy:

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

(fungerer også på FreeBSD og derivater).

Svar

I Hvis du bruker GNU grep, kan du bruke alternativet -r eller --recursive for å gjøre dette enkle funnet for deg:

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

Du trenger bare find hvis du trenger mer avanserte predikater.

Kommentarer

  • Avhengig av versjonen av GNU grep, grep kan se eller ikke se på symlinker eller krysse symlinks til kataloger. Du kan også finne noen variasjoner i håndteringen av andre typer ikke-vanlige filer.

Svar

Du kan fortelle grep å inkludere filnavnet i utdataene. Så hvis det er en kamp, vil den vises på konsollen; hvis det ikke samsvarer med en fil, blir det ikke skrevet ut en linje for den filen.

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

Fra 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. 

Hvis filene dine kan ha navn med mellomrom, må du bytte rør for å bruke NUL-tegn som en separator. Den fullstendige kommandoen vil nå se slik ut:

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

Svar

Du kan prøv noe sånt som:

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

Denne exec grep-kommandoen for hver fil, oppdaget av find-kommandoen og dens standard finn-kommandofunksjon

Svar

Bruk -l argumentet.

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

En mer finnisk bruk vil være:

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

Svar

Der er grep alternativer som som standard leverer resultatene i ønsket format. De 2 mest populære som jeg kjenner er ag (aka «the silver searcher») og ack. ag annonseres som et raskere alternativ til 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) { ... 

Jeg kan ikke vise deg her, men utdataene er pent fargede. Jeg får filnavnene i en olivengrønn, linjenumrene i gullgult og det matchede stykket i hver linje i blodrødt. Fargene kan tilpasses skjønt.

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *