2012-03-05 23:28:16 +0000 2012-03-05 23:28:16 +0000
148
148

Come ignorare certi nomi di file usando "find"?

Uno dei miei comandi BASH preferiti è:

find . -name '*.*' -exec grep 'SearchString' {} /dev/null \;

che cerca il contenuto di tutti i file nella e sotto la directory corrente per la stringa di ricerca specificata. Come sviluppatore, questo è stato utile a volte.

A causa del mio progetto attuale, e della struttura del mio codebase, tuttavia, vorrei rendere questo comando BASH ancora più avanzato, non cercando alcun file che si trovi in o sotto una directory che contiene “.svn”, o qualsiasi file che finisca con “.html”

La pagina MAN per find mi ha un po’ confuso. Ho provato ad usare -prune, e mi ha dato un comportamento strano. Nel tentativo di saltare solo le pagine .html (per iniziare), ho provato:

find . -wholename './*.html' -prune -exec grep 'SearchString' {} /dev/null \;

e non ho ottenuto il comportamento che speravo. Credo che mi manchi il senso di -prune. Potreste aiutarmi?

Grazie

Risposte (3)

209
209
209
2012-03-06 00:40:37 +0000

Potete usare la funzione negate (!) di find per non far corrispondere i file con nomi specifici:

find . ! -name '*.html' ! -path '*.svn*' -exec grep 'SearchString' {} /dev/null \;

Quindi se il nome finisce in .html o contiene .svn da qualche parte nel percorso, non corrisponderà, e quindi l'esecuzione non sarà eseguita.

12
12
12
2012-03-06 13:54:15 +0000

Ho avuto lo stesso problema per molto tempo, e ci sono diverse soluzioni che possono essere applicabili in diverse situazioni:

  • ack-grep è una sorta di “grep dello sviluppatore” che per default salta le directory di controllo della versione e i file temporanei. La pagina man spiega come cercare solo specifici tipi di file e come definire il proprio . Le opzioni grep e --exclude di
  • --exclude-dir possono essere usate molto facilmente per saltare file globs e singole directory (nessun globbing per le directory, purtroppo).
  • find . \( -type d -name '.svn' -o -type f -name '*.html' \) -prune -o -print0 | xargs -0 grep ... dovrebbe funzionare, ma le opzioni precedenti sono probabilmente meno fastidiose a lungo termine.
9
9
9
2012-03-06 03:29:21 +0000

Il seguente comando find sfronda le directory i cui nomi contengono .svn, anche se non scende nella directory, il nome del percorso sfrondato viene stampato …(-name '*.svn' è la causa!) ..

Si possono filtrare i nomi delle directory tramite: grep -d skip che salta silenziosamente tali input “nomi di directory”.

Con GNU grep, puoi usare -H invece di /dev/null. Come piccola questione collaterale: può essere molto più veloce di `\;`, ad esempio per 1 milione di file di una riga, usando `\;` ci voleva _4m20s_, usando ci voleva solo 1.2s.

Il seguente metodo usa xargs invece di -exec, e assume che non ci siano newlines \n in nessuno dei tuoi nomi di file. Come usato qui, xargs è molto simile a “ di find.

xargs può passare nomi di file che contengono spazi consecutivi cambiando il delimitatore di input in '\n' con l'opzione -d.

Questo esclude le directory il cui nome contiene .svn e cerca solo i file che non finiscono con .html.

find . \( -name '*.svn*' -prune -o ! -name '*.html' \) |
   xargs -d '\n' grep -Hd skip 'SearchString'