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
- Gerelateerd (op Ask Ubuntu ): Zoek recursief een patroon / tekst alleen in de opgegeven bestandsnaam van een directory?
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.