Käytin tätä paljon, parannus, jonka yritän saavuttaa, on välttää kaikutiedostojen nimet, jotka eivät sopineet grep. Parempi tapa tehdä tämä?
for file in `find . -name "*.py"`; do echo $file; grep something $file; done
Kommentit
- Liittyvät (osoitteessa Kysy Ubuntulta ): Hae rekursiivisesti kuviota / tekstiä vain hakemiston määritetystä tiedostonimestä?
vastaus
find . -name "*.py" -exec grep something {} \; -print
tulostaisi tiedostonimen vastaavien rivien jälkeen.
find . -name "*.py" -exec grep something /dev/null {} +
tulosta tiedostonimi jokaisen vastaavan rivin eteen (lisätään /dev/null
tapaukseen, jossa on vain yksi vastaava tiedosto nimellä grep
ei tulosta tiedostonimeä, jos se on välittänyt vain yhden tutkittavan tiedoston. GNU-toteutus grep
: lla on vaihtoehto vaihtoehto -H
).
find . -name "*.py" -exec grep -l something {} +
tulostaa vain niiden tiedostojen nimet, joissa on vähintään yksi vastaava rivi.
Tulostaaksesi tiedostonimen ennen vastaavia rivejä, voit käyttää awk sen sijaan:
find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +
Tai soita grep
kahdesti kullekin tiedostolle – vaikka ”d on vähemmän tehokas, koska se suorittaa vähintään yhden grep
-komennon ja enintään kaksi kullekin tiedostolle (ja lue tiedoston sisältö kahdesti ):
find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;
Joka tapauksessa et halua käyttää silmukkaa find
tällöin ja muista lainata muuttujat .
Jos haluat käyttää shell-silmukkaa, GNU-työkaluilla:
find . -name "*.py" -exec grep -l --null something {} + | xargs -r0 sh -c " for file do printf "%s\n" "$file" grep something < "$file" done" sh
(toimii myös FreeBSD: llä ja johdannaisilla).
Vastaa
I Jos käytät GNU grep -ohjelmaa, voit käyttää sen vaihtoehtoa -r
tai --recursive
tehdäksesi tämän yksinkertaisen haun sinulle:
grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match
Tarvitset vain find
, jos tarvitset edistyneemmät predikaatit.
Kommentit
- GNU-version mukaan
grep
,grep
voi etsiä symboleita tai hakemistoihin viittaavia linkkejä. Saatat löytää joitain muunnelmia muun tyyppisten ei-säännöllisten tiedostojen käsittelystä.
Vastaa
Sinä voi kertoa grep: lle sisällyttävän tiedostonimen lähtöön. Joten jos on ottelu, se näkyy konsolissa; jos tiedostossa ei ole vastaavuutta, tälle tiedostolle ei tulosteta riviä.
find . -name "*.py" | xargs grep -n -H something
Kohdasta 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.
Jos tiedostoissasi voi olla nimiä, joissa on välilyöntejä, sinun on vaihdettava putkea, jotta NUL-merkkejä käytetään erottajana. Koko komento näyttää nyt tältä:
find . -name "*.py" -print0 | xargs -0 grep -n -H something
Vastaa
Voit kokeile jotain seuraavaa:
find . -name "*.py:" -exec grep -l {} \;
Tämä exec grep -komento jokaiselle tiedostolle, löydetty find-komennolla ja sen tavallisella find-komento-ominaisuudella
Vastaa
Käytä -l
-argumenttia.
for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done
Löytävämpi käyttö olisi:
for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done
vastaus
Siellä ovat grep
vaihtoehtoja, jotka antavat tulokset oletusarvoisesti haluamassasi muodossa. Kaksi suosituinta, jotka tiedän, ovat ag
(alias ”hopeanhaku”) ja ack
. ag
mainostetaan nopeammin vaihtoehtona 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) { ...
En voi näyttää sinua täällä, mutta tulos on siististi värillinen. Sain tiedostonimet oliivinvihreiksi, viivanumerot kullankeltaisiksi ja kunkin rivin vastaava kappale veripunaiseksi. Värit ovat kuitenkin muokattavissa.