¿Cómo uso la opción grep --include para varios tipos de archivos?

98

Cuando quiero grep todos los archivos html en algún directorio, hago lo siguiente

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

que funciona bien. El problema es cómo agrupar todos los archivos html, htm, php en algún directorio.

Desde este Use grep --exclude / - incluya sintaxis para no grep a través de ciertos archivos , parece que puedo hacer lo siguiente

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

Pero, lamentablemente, no funcionaría para mí.
FYI, mi versión de grep es 2.5.1.

tianyapiaozi
fuente

Respuestas:

137

Puede utilizar varias --includebanderas. Esto funciona para mi:

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

Sin embargo, puede hacer lo Deruijtersugerido. Esto funciona para mi:

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

No olvide que puede usar findy xargspara este tipo de cosas:

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

HTH

Steve
fuente
1
Veo el problema. Usé --include = " . {Html, php}" para evitar que el shell se expanda ' ', lo que al mismo tiempo detiene el shell para expandirse {html, php}. Parece que el signo igual en --include = * puede evitar que el shell expanda '*'.
tianyapiaozi
xargs no es realmente un sustituto; Muchas veces, cuando necesita esta función, está tratando con más archivos de los que puede manejar xargs.
James Moore
2
@JamesMoore: Eche un vistazo a GNU Parallel . A menudo se puede utilizar como sustituto de xargs. Este es también digno de una lectura rápida. HTH.
Steve
3
@tianyapiaozi: Tiene razón en que las citas en torno a la expansión de la abrazadera son el problema; sin citar, sin embargo, *sigue siendo objeto de comodines como parte de la ficha que está incrustado en , sólo sucede que no encuentro nada en este caso, porque sólo los archivos , literalmente, un nombre como --include=foo.htmlse correspondería. Para estar seguro, cite el *(que puede hacer individualmente \*). Como ventaja adicional, esto hace que sea visualmente más claro que no es el caparazón el que debería realizar el globbing en este caso.
mklement0
2
En cuanto a la findsolución: usar en -exec grep "pattern" {} +lugar de | xargs grep "pattern"es más robusto (maneja nombres de archivo con espacios, por ejemplo) y más eficiente.
mklement0
32

Usando {html,php,htm}sólo puede funcionar como una expansión de llaves , que es un no estándar (no compatible con POSIX) característica de bash, kshy zsh.

  • En otras palabras: no intente usarlo en un script que tenga como objetivo /bin/sh, use múltiples argumentos explícitos--include en ese caso.

  • grepen sí mismo no comprende la {...}notación.

Para que se reconozca una expansión de llaves, debe ser un token sin comillas (parte de a) en la línea de comando.

Una expansión de llaves se expande a múltiples argumentos , por lo que, en el caso que nos ocupa, greptermina viendo múltiples --include=... opciones, como si las hubiera pasado individualmente.

Los resultados de una expansión de llaves están sujetos a globbing (expansión de nombre de archivo) , que tiene dificultades :

  • Cada argumento resultante podría expandirse aún más a nombres de archivo coincidentes si contiene metacaracteres globales sin comillas como *.
    Si bien esto es poco probable con tokens como --include=*.html(por ejemplo, tendría que tener un archivo con un nombre literalmente similar --include=foo.htmlpara que algo coincida), vale la pena tenerlo en cuenta en general.

  • Si la nullglobopción de shell está activada ( shopt -s nullglob) y el globbing no coincide con nada , el argumento se descartará .

Por lo tanto, para una solución completamente robusta , use lo siguiente:

grep -R '--include=*.'{html,php,htm} pattern /some/path
  • '--include=*.'se trata como literal , debido a que está entre comillas simples ; esto evita la interpretación inadvertida de *un carácter globular.

  • {html,php,htm}, la - por necesidad - expansión de llaves sin comillas [1] , se expande a 3 argumentos que, debido a {...} que siguen directamente al '...'token , incluyen ese token.

  • Por lo tanto, después de que el shell elimine las comillas, los siguientes 3 argumentos literales se pasan finalmente agrep :

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

[1] Más exactamente, son solo las partes relevantes para la sintaxis de la expansión de llaves las que deben estar sin comillas, los elementos de la lista aún pueden estar entrecomillados individualmente y deben serlo si contienen metacaracteres globbing que podrían resultar en globbing no deseado después de la expansión de llaves; aunque no es necesario en este caso, lo anterior podría escribirse como
'--include=*.'{'html','php','htm'}

mklement0
fuente
1
Muchas gracias por esta publicación. ¡Las publicaciones geniales no solo responden a la pregunta, sino que también te enseñan algo nuevo! Esto es especialmente útil para aquellos de nosotros que escribimos sobre algo que debe ser compatible con POSIX. ¡Cualquiera que use Mac OS X debería mirar aquí!
sabalaba
@sabalaba: Me alegra escucharlo, pero para ser claro: si bien la expansión de llaves no es compatible con POSIX, funciona bashen cualquier plataforma que se bashejecute.
mklement0
9

Intente eliminar las comillas dobles

grep --include=*.{html,php,htm} pattern -R /some/path
Deruijter
fuente
@tianyapiaozi Inténtalo grep --include=\*.{html,php,htm} pattern -R /some/path. Funcionó para mí.
Hyunjun Kim
4

esto no esta funcionando?

  grep pattern  /some/path/*.{html,php,htm} 
Vijay
fuente
Realmente no. Los archivos pueden residir en el subdirectorio del subdirectorio
tianyapiaozi
2

Prueba esto. -r hará una búsqueda recursiva. -s suprimirá los errores de archivo no encontrado. -n le mostrará el número de línea del archivo donde se encuentra el patrón.

    grep "pattern" <path> -r -s -n --include=*.{c,cpp,C,h}
Pradeep
fuente
Esta es la mejor respuesta para mí en particular, y creo que puede poner -rsn en lugar de -r -s -n (pero eso es quisquilloso).
delgado
Normalmente utilizo -rns . Para mayor claridad en el ejemplo, tuve que mencionar -r -n -s :-) Me alegro de que haya ayudado.
Pradeep
Recomiendo agregar -Ial conjunto estándar. Omite archivos binarios (que casi nunca se buscan), por lo que aumenta la eficiencia. Luego vamos, grep -rIns ...que acústicamente suena muy bien :)
sangriento
2

Funciona con el mismo propósito, pero sin --includeopción. También funciona en grep 2.5.1.

grep -v -E ".*\.(html|htm|php)"
Kohei Mikami
fuente
0

Usar grepcon findcomando

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

También puede utilizar -regexy -regextypeopciones.

Príncipe Juan Wesley
fuente