come si usa l'opzione grep --include per più tipi di file?


98

Quando voglio grep tutti i file html in una directory, faccio quanto segue

grep --include="*.html" pattern -R /some/path

che funziona bene. Il problema è come grep tutti i file html, htm, php in qualche directory?

Da questo Usa grep --exclude / - include la sintassi per non grep attraverso determinati file , sembra che io possa fare quanto segue

grep --include="*.{html,php,htm}" pattern -R /some/path

Ma purtroppo non funzionerebbe per me.
Cordiali saluti, la mia versione di grep è 2.5.1.

Risposte:


137

Puoi usare più --includeflag. Questo funziona per me:

grep -r --include=*.html --include=*.php --include=*.htm "pattern" /some/path/

Tuttavia, puoi fare come Deruijtersuggerito. Questo funziona per me:

grep -r --include=*.{html,php,htm} "pattern" /some/path/

Non dimenticare che puoi usare finde xargsper questo genere di cose per:

find /some/path/ -name "*.htm*" -or -name "*.php" | xargs grep "pattern"

HTH


1
Capisco il problema. Ho usato --include = " . {Html, php}" per impedire l'espansione della shell ' ' che allo stesso tempo ferma la shell per espandere {html, php}. Sembra che il segno di uguale in --include = * sia in grado di impedire alla shell di espandere '*'.
tianyapiaozi

xargs non è realmente un sostituto; molte volte quando hai bisogno di questa funzione, hai a che fare con più file di quanti ne gestirà xargs.
James Moore

2
@JamesMoore: dai un'occhiata a GNU Parallel . Può spesso essere usato come sostituto di xargs. Questa è anche la pena di una lettura veloce. HTH.
Steve

3
@ tianyapiaozi: Hai ragione sul fatto che la citazione intorno all'espansione della parentesi graffa è il problema; senza la citazione, tuttavia, *è ancora soggetto a globbing come parte del token in cui è incorporato , in questo caso accade solo che non corrisponda a nulla, perché solo i file letteralmente denominati in modo simile --include=foo.htmlpotrebbero corrispondere. Per sicurezza, cita il *(cosa che puoi fare individualmente \*). Come bonus aggiuntivo, questo rende visivamente più chiaro che non è il guscio che dovrebbe eseguire il globbing in questo caso.
mklement0

2
Per quanto riguarda la findsoluzione: usare -exec grep "pattern" {} +invece di | xargs grep "pattern"è più robusto (gestisce i nomi dei file con spazi, ad esempio) oltre che più efficiente.
mklement0

32

Usando {html,php,htm}può funzionare solo come espansione tutore , che è un non standard (non POSIX) caratteristica bash, kshe zsh.

  • In altre parole: non provare a usarlo in uno script che ha come target /bin/sh- usa argomenti multipli espliciti--include in quel caso.

  • grepdi per sé non comprende la {...}notazione.

Affinché un'espansione di parentesi graffa venga riconosciuta, deve essere un token non quotato (parte di a) sulla riga di comando.

Un'espansione di parentesi graffa si espande a più argomenti , quindi nel caso in questione grepfinisce per vedere più --include=... opzioni, proprio come se le avessi passate singolarmente.

I risultati di un'espansione di parentesi graffe sono soggetti a globbing (espansione del nome del file) , che presenta delle insidie :

  • Ogni argomento risultante potrebbe essere ulteriormente espanso ai nomi di file corrispondenti se capita di contenere metacaratteri globbing non quotati come *.
    Anche se questo è improbabile con token come --include=*.html(ad esempio, dovresti avere un file letteralmente chiamato qualcosa come --include=foo.htmlper far corrispondere qualcosa), vale la pena tenerlo a mente in generale.

  • Se l' nullglobopzione della shell è attivata ( shopt -s nullglob) e il globbing non corrisponde a nulla , l'argomento verrà scartato .

Pertanto, per una soluzione completamente robusta , utilizzare quanto segue:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'è trattato come un letterale , perché è un apice singolo ; questo impedisce l'interpretazione involontaria di *come un personaggio globbing.

  • {html,php,htm}, l' espansione di parentesi graffa - di necessità - non quotata [1] , si espande a 3 argomenti, che, a causa del {...} seguire direttamente il '...'token , includono quel token.

  • Pertanto, dopo la rimozione delle virgolette dalla shell, i seguenti 3 argomenti letterali vengono infine passati agrep :

    • --include=*.html
    • --include=*.php
    • --include=*.htm

[1] Più precisamente, sono solo le parti rilevanti per la sintassi dell'espansione delle parentesi graffe che devono essere non quotate , gli elementi della lista possono ancora essere citati individualmente e devono esserlo se contengono metacaratteri globbing che potrebbero provocare un globbing indesiderato dopo l'espansione della parentesi graffa; sebbene non sia necessario in questo caso, quanto sopra potrebbe essere scritto come
'--include=*.'{'html','php','htm'}


1
La ringrazio molto per questo post. I post fantastici non solo rispondono alla domanda ma ti insegnano qualcosa di nuovo! Ciò è particolarmente utile per quelli di noi che scrivono su qualcosa che deve essere conforme a POSIX. Chiunque utilizzi Mac OS X dovrebbe guardare qui!
sabalaba

@sabalaba: Sono contento di sentirlo, ma per essere chiari: sebbene l'espansione delle parentesi graffe non sia conforme a POSIX, funziona bashsu qualsiasi piattaforma in bashesecuzione.
mklement0

9

Prova a rimuovere le virgolette doppie

grep --include=*.{html,php,htm} pattern -R /some/path

@tianyapiaozi Prova grep --include=\*.{html,php,htm} pattern -R /some/path. Ha funzionato per me.
Hyunjun Kim

4

non funziona?

  grep pattern  /some/path/*.{html,php,htm} 

Non proprio. I file possono risiedere nella sottodirectory della sottodirectory
tianyapiaozi

2

Prova questo. -r eseguirà una ricerca ricorsiva. -s sopprimerà gli errori di file non trovato. -n ti mostrerà il numero di riga del file in cui si trova il modello.

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}

Questa è la risposta migliore per me in particolare, e penso che tu possa mettere -rsn invece di -r -s -n (ma questo è pignolo).
slim

Di solito uso -rns . Per chiarezza nell'esempio ho dovuto menzionare -r -n -s :-) Sono contento che abbia aiutato.
Pradeep

Consiglio di aggiungere -Ial set standard. Salta i file binari (che non vengono quasi mai cercati) quindi aumenta l'efficienza. Poi andiamo, grep -rIns ...che suona bene acusticamente :)
sanguinosa

2

Funziona per lo stesso scopo, ma senza --includeopzioni. Funziona anche su grep 2.5.1.

grep -v -E ".*\.(html|htm|php)"

0

Usa grepcon findcomando

find /some/path -name '*.html' -o -name '*.htm' -o -name '*.php' -type f 
 -exec grep PATTERN {} \+

Puoi anche usare -regexe -regextypeopzioni.

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.