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

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.

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *