Jeg brugte dette meget, den forbedring, jeg prøver at opnå, er at undgå ekkofilnavne, der ikke matchede i grep. Bedre måde at gø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 udskrive filnavnet efter de matchende linjer.

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

udskriver filnavnet foran hver matchende linje (vi tilføjer /dev/null i det tilfælde, hvor der kun er en matchende fil som grep udskriver ikke filnavnet, hvis den kun har sendt en fil til at se i. GNU-implementeringen af grep har en -H mulighed for det som et alternativ).

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

udskriver kun filnavne på de filer, der har mindst en matchende linje.

Hvis du vil udskrive filnavnet før de matchende linjer, kan du bruge 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 gange for hver fil – selvom det “ville være mindre effektivt, da det ville køre mindst en grep -kommando og op til to for hver fil (og læs indholdet af filen to gange ):

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

Under alle omstændigheder du vil ikke løkke output fra find sådan og husk at citere din variabler .

Hvis du vil bruge en shell-loop med GNU-værktøjer:

 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 bruger GNU grep, kan du bruge dens -r eller --recursive mulighed for at gøre dette enkle fund for dig:

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

Du har kun brug for find mere avancerede prædikater.

Kommentarer

  • Afhængigt af versionen af GNU grep, grep ser måske eller måske ikke inde i symlinks eller krydser symlinks til mapper. Du kan også finde nogle variationer i håndteringen af andre typer ikke-almindelige filer.

Svar

Dig kan fortælle grep at inkludere filnavnet i output. Så hvis der er en kamp, vises den på konsollen; hvis der ikke er nogen match i en fil, udskrives der ingen linje for den fil.

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 dine filer muligvis har navne med mellemrum, skal du skifte rør for at bruge NUL-tegn som en separator. Den fulde kommando vil nu se sådan ud:

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

Svar

Du kan prøv noget som:

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

Denne exec grep-kommando for hver fil, opdaget af find-kommandoen og dens standardfind kommandofunktion

Svar

Brug argumentet -l.

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

En mere findish brug ville være:

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

Svar

Der er grep alternativer, der som standard udlæser deres resultater i det ønskede format. De 2 mest populære, som jeg kender, er ag (aka “the silver searcher”) og ack. ag annonceres som et hurtigere 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 dig her, men output er pænt farvet. Jeg får filnavnene i en olivengrøn, linjenumrene i guldgult og det matchede stykke i hver linje i blodrødt. Farverne kan dog tilpasses.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *