trova ed esegui l'eco dei nomi dei file solo con il pattern trovato


Risposte:


23
find . -name '*.py' -exec grep something {} \; -print

stampa il nome del file dopo le righe corrispondenti.

find . -name '*.py' -exec grep something /dev/null {} +

stamperebbe il nome del file davanti a ogni riga corrispondente (aggiungiamo /dev/nullper il caso in cui c'è solo un file corrispondente poiché grepnon stampa il nome del file se viene passato solo un file in cui cercare. L'implementazione GNU di grepha -Hun'opzione per quello come alternativa).

find . -name '*.py' -exec grep -l something {} +

stamperebbe solo i nomi dei file che hanno almeno una riga corrispondente.

Per stampare il nome del file prima delle righe corrispondenti, è possibile utilizzare invece awk:

find . -name '*.py' -exec awk '
  FNR == 1 {filename_printed = 0}
  /something/ {
    if (!filename_printed) {
      print FILENAME
      filename_printed = 1
    }
    print
  }' {} +

Oppure chiama grepdue volte per ogni file, anche se sarebbe meno efficiente in quanto eseguirà almeno un grepcomando e fino a due per ogni file (e leggerà il contenuto del file due volte):

find . -name '*.py' -exec grep -l something {} \; \
                    -exec grep something {} \;

In ogni caso, non vuoi passare in rassegna l'output di findcosì e ricordati di citare le tue variabili .

Se volevi usare un loop shell, con gli strumenti 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

(funziona anche su FreeBSD e derivati).


6

Se stai usando GNU grep, puoi usare la sua -ro --recursiveopzione per fare questa semplice ricerca per te:

grep -r --include '*.py' -le "$regexp" ./ # for filenames only
grep -r --include '*.py' -He "$regexp" ./ # for filenames on each match

Hai bisogno solo findse hai bisogno di predicati più avanzati.


1
A seconda della versione di GNU grep, greppuò o meno guardare all'interno dei symlink o attraversare i symlink verso le directory. Potresti anche trovare alcune variazioni nella gestione di altri tipi di file non regolari.
Stéphane Chazelas,

5

Puoi dire a grep di includere il nome del file nell'output. Quindi se c'è una corrispondenza verrà mostrata sulla console; se non esiste alcuna corrispondenza all'interno di un file, nessuna riga verrà stampata per quel file.

find . -name "*.py" | xargs grep -n -H something

Dal 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.

Se i tuoi file potrebbero avere nomi con spazi, devi cambiare la pipe per usare i caratteri NUL come separatore. Il comando completo ora avrà questo aspetto:

find . -name "*.py" -print0 | xargs -0 grep -n -H something

1

Puoi provare qualcosa del tipo:

find . -name "*.py:" -exec grep -l {} \;

Questo comando exec grep per ogni file, scoperto dal comando find e dalla sua funzione standard di comando find


1

Usa l' -largomento.

for file in `find . -name "*.py"`; do grep -l something $file && grep something $file; done

Un utilizzo più mirato sarebbe:

for file in $(find . -name '*.py' -exec grep -l something '{}' +); do echo "$file"; grep something $file; done

1

Esistono grepalternative che, per impostazione predefinita, producono i risultati nel formato desiderato. I 2 più popolari che conosco sono ag(aka "il cercatore d'argento") e ack. agè pubblicizzato come alternativa più veloce a 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) {
...

Non posso mostrarti qui, ma l'output è ben colorato. Ottengo i nomi dei file in un verde oliva, i numeri delle righe in giallo oro e il pezzo abbinato in ogni riga in rosso sangue. I colori sono comunque personalizzabili.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.