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
- Relateret (på Spørg Ubuntu ): Søg kun rekursivt i et mønster / tekst i det angivne filnavn i en mappe?
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.