Použil jsem to hodně, zlepšení, které se snažím dosáhnout, je vyhnout se názvům souborů echa, které se neshodovaly grep. Lepší způsob, jak to udělat?
for file in `find . -name "*.py"`; do echo $file; grep something $file; done
Komentáře
- Související (na Zeptejte se Ubuntu ): Rekurzivně prohledávat vzor / text pouze v zadaném názvu souboru v adresáři?
Odpověď
find . -name "*.py" -exec grep something {} \; -print
vytiskne název souboru za odpovídajícími řádky.
find . -name "*.py" -exec grep something /dev/null {} +
vytiskne název souboru před každý odpovídající řádek (přidáme /dev/null
pro případ, že existuje pouze jeden shoda souboru jako grep
nevytiskne název souboru, pokud předá pouze jeden soubor, který má být vyhledán. Implementace GNU grep
má alternativu -H
).
find . -name "*.py" -exec grep -l something {} +
vytiskne pouze názvy souborů souborů, které mají alespoň jeden odpovídající řádek.
Chcete-li vytisknout název souboru před odpovídajícími řádky, můžete použít awk místo toho:
find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +
Nebo volejte grep
dvakrát pro každý soubor – i když by to bylo méně efektivní, protože by spustil alespoň jeden grep
příkaz a až dva pro každý soubor (a přečíst obsah souboru dvakrát ):
find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;
V každém případě Nechcete smyčku přes výstup find
takového a nezapomeňte uvést své proměnné .
Pokud jste chtěli použít smyčku prostředí, s nástroji GNU:
find . -name "*.py" -exec grep -l --null something {} + | xargs -r0 sh -c " for file do printf "%s\n" "$file" grep something < "$file" done" sh
(funguje také na FreeBSD a derivátech).
Odpověď
I Pokud používáte GNU grep, můžete použít toto -r
nebo --recursive
toto jednoduché hledání:
grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match
Potřebujete find
, pouze pokud potřebujete pokročilejší predikáty.
Komentáře
- V závislosti na verzi GNU
grep
,grep
se může, ale nemusí dívat dovnitř symbolických odkazů nebo procházet symbolické odkazy do adresářů. Můžete také najít určité varianty zpracování jiných typů nepravidelných souborů.
Odpovědět
Vy může říct grepu, aby do výstupu zahrnul název souboru. Pokud tedy existuje shoda, zobrazí se na konzole; pokud v souboru není shoda, nebude pro tento soubor vytištěn žádný řádek.
find . -name "*.py" | xargs grep -n -H something
Z 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.
Pokud by vaše soubory mohly mít názvy s mezerami, musíte přepnout kanál, aby jako oddělovač používaly znaky NUL. Celý příkaz bude nyní vypadat takto:
find . -name "*.py" -print0 | xargs -0 grep -n -H something
Odpovědět
Můžete zkuste něco jako:
find . -name "*.py:" -exec grep -l {} \;
Tento příkaz exec grep pro každý soubor objevený příkazem find a jeho standardní funkcí příkazu find
Odpověď
Použijte argument -l
.
for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done
Další vyhledávací použití by bylo:
for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done
Odpověď
Tam jsou grep
alternativy, které ve výchozím nastavení zobrazují výsledky ve formátu, který chcete. 2 nejoblíbenější z nich, které znám, jsou ag
(aka „stříbrný vyhledávač“) a ack
. ag
je inzerován jako rychlejší alternativa k 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) { ...
Tady vás nemohu ukázat, ale výstup je úhledně barevný. Názvy souborů dostávám olivově zelenou, čísla řádků zlatožlutou a odpovídající část v každém řádku krvavě červenou. Barvy jsou přizpůsobitelné.