Am folosit acest lucru mult, îmbunătățirea pe care încerc să o realizez este să evit numele fișierelor ecou care nu se potriveau în grep. O modalitate mai bună de a face acest lucru?
for file in `find . -name "*.py"`; do echo $file; grep something $file; done
Comentarii
- Înrudit (pe Întrebați Ubuntu ): Căutați recursiv un model / text numai în numele fișierului specificat al unui director?
Răspuns
find . -name "*.py" -exec grep something {} \; -print
ar imprima numele fișierului după liniile potrivite.
find . -name "*.py" -exec grep something /dev/null {} +
ar imprima numele fișierului în fața fiecărei linii potrivite (adăugăm /dev/null
pentru cazul în care există doar unul fișierul care se potrivește ca grep
nu tipărește numele fișierului dacă a trecut doar un fișier de căutat. Implementarea GNU a grep
are o opțiune -H
pentru aceasta ca alternativă).
find . -name "*.py" -exec grep -l something {} +
ar imprima numai numele fișierelor fișierelor care au cel puțin o linie potrivită.
Pentru a imprima numele fișierului înainte liniile potrivite, puteți utiliza awk în schimb:
find . -name "*.py" -exec awk " FNR == 1 {filename_printed = 0} /something/ { if (!filename_printed) { print FILENAME filename_printed = 1 } print }" {} +
Sau apelați grep
de două ori pentru fiecare fișier – deși „ar fi mai puțin eficient deoarece ar rula cel puțin o comandă grep
și până la două pentru fiecare fișier (și citiți conținutul fișierului de două ori ):
find . -name "*.py" -exec grep -l something {} \; \ -exec grep something {} \;
În orice caz, nu doriți să faceți o buclă peste ieșirea find
așa și nu uitați să citați variabile .
Dacă doriți să utilizați o buclă shell, cu instrumentele 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
(funcționează și pe FreeBSD și derivate).
Răspuns
I dacă folosiți GNU grep, puteți utiliza opțiunea -r
sau --recursive
pentru a face acest lucru simplu pentru dvs.:
grep -r --include "*.py" -le "$regexp" ./ # for filenames only grep -r --include "*.py" -He "$regexp" ./ # for filenames on each match
Ai nevoie de find
numai dacă ai nevoie predicate mai avansate.
Comentarii
- În funcție de versiunea GNU
grep
,grep
poate sau nu să privească în interiorul linkurilor simbolice sau să traverseze linkurile simbolice către directoare. Puteți găsi, de asemenea, unele variații în tratarea altor tipuri de fișiere care nu sunt obișnuite.
Răspunde
Tu poate spune grep să includă numele fișierului în ieșire. Deci, dacă există un meci, acesta va fi afișat pe consolă; dacă nu există nicio potrivire într-un fișier, nu va fi tipărită nicio linie pentru acel fișier.
find . -name "*.py" | xargs grep -n -H something
Din 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.
Dacă fișierele dvs. pot avea nume cu spații în ele, trebuie să schimbați conducta pentru a utiliza caracterele NUL ca separator. Comanda completă va arăta astfel:
find . -name "*.py" -print0 | xargs -0 grep -n -H something
Răspuns
Puteți încercați ceva de genul:
find . -name "*.py:" -exec grep -l {} \;
Această comandă exec grep pentru fiecare fișier, descoperită de comanda find și de funcția standard de comandă find
Răspuns
Utilizați argumentul -l
.
for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done
O utilizare mai detaliată ar fi:
for file in $(find . -name "*.py" -exec grep -l something "{}" +); do echo "$file"; grep something $file; done
Răspuns
Acolo sunt grep
alternative care în mod implicit produc rezultatele în formatul dorit. Cele mai populare 2 pe care le știu sunt ag
(alias „căutătorul de argint”) și ack
. ag
este promovat ca o alternativă mai rapidă la 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) { ...
Nu vă pot arăta aici, dar rezultatul este bine colorat. Primesc numele fișierelor într-un verde măsliniu, numerele de linie în galben auriu și piesa potrivită în fiecare linie în roșu sânge. Culorile sunt personalizabile.