Estoy buscando una declaración de clase en un sitio con cientos de archivos PHP. ¿Cómo puedo hacer esto en la carpeta y subcarpetas actuales usando grep ?
Probé cd
ing a la carpeta y luego algo parecido
grep -r 'class MyClass' *.php
Estoy buscando una declaración de clase en un sitio con cientos de archivos PHP. ¿Cómo puedo hacer esto en la carpeta y subcarpetas actuales usando grep ?
Probé cd
ing a la carpeta y luego algo parecido
grep -r 'class MyClass' *.php
Respuestas:
Recomiendo que uses algo como ctags en lugar de hacerlo con grep. Sin embargo, si quieres, puedes hacer algo como
find <top level dir> -name \*.php | xargs grep "class MyClass"
Por supuesto, esto supone que tiene un solo espacio entre class
y myClass
que podría no ser cierto. Sin embargo, es fácil cambiar la expresión regular para buscar cualquier cantidad de espacios en blanco.
Si usa -r
, probablemente desee buscar recursivamente solo el directorio actual :
grep -r 'class MyClass' .
Tenga en cuenta el período al final de lo anterior.
Lo que dijo grep
fue que quería que buscara recursivamente cada *.php
archivo o directorio , pero que probablemente no tenía ningún directorio que terminara en una extensión .php. Lo anterior es la forma más simple posible de hacer la búsqueda, pero también incluye archivos de otros tipos, lo cual es especialmente problemático cuando tiene directorios .svn en todas partes. Si no tiene muchos otros tipos de archivos, lo anterior es generalmente suficiente y funciona bien.
La mayoría de las encarnaciones de grep no tienen una forma de especificar las extensiones de archivo que se pueden buscar, por lo que generalmente usa find junto con él:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} \;
-iname
le dice a algunas versiones de grep que desea hacer una búsqueda de nombre de archivo que no distingue entre mayúsculas y minúsculas, pero muchas de las variantes de find que no son GNU no lo admiten, por lo que podría usarlo -name
en su lugar.
La -exec
opción anterior tiene el efecto secundario de invocar grep para cada archivo, lo cual es bastante costoso.
Aún otras versiones de grep soportan a +
que le dice a find que agregue los argumentos juntos para reducir el número de invocaciones del ejecutable:
find <startDir> -iname '*.php' -exec grep 'class[ \t]*MyClass' {} + \;
Una forma frecuentemente recomendada de reducir las invocaciones es usar xargs que dispararán grep tan pocas como sea posible, pero tantas veces como sea necesario:
find <startDir> -iname \*.php | xargs grep "class[ \t]*MyClass"
xargs
es lo suficientemente inteligente como para pasar grep hasta el número máximo de argumentos admitidos en la línea de comando, pero la variación anterior no maneja muy bien ciertos caracteres como espacios. Por ejemplo, si 'el archivo.php' un nombre de archivo grep recibiría 'el' como argumento y 'archivo.php' como argumento para que no se encuentren ambos. En su lugar usamos:
find <startDir> -iname \*.php -print0 | xargs -0 grep "class[ \t]*MyClass"
print0
y -0
trabajen juntos y usen argumentos seguidos de un carácter nulo para que el argumento se identifique completa e inequívocamente.
Si alguna vez tiene más de un espacio después class
, o una pestaña, es posible que desee permitir más caracteres cambiando la expresión regular:class[ \t]*MyClass
Esta publicación en StackOverflow tiene otros ejemplos y muestra cómo excluir ciertos directorios, como los directorios .svn.
grep -r 'class MyClass' *.php
buscará en todas las carpetas con nombres que terminen en .php
grep -r 'class MyClass' . | grep .php
buscará la clase MyClass en todos los archivos en todas las subcarpetas, luego solo devolverá los que tengan .php en ellos.
find . -type f -name *.php -print -exec grep \"class MyClass\" {} \;
le dará el contenido de la línea en la que se encuentra, así como la ruta al archivo.
Probablemente desee insensibilidad a mayúsculas y tolerancia de espacios en blanco, y grep terminará si no encuentra ninguna instancia del patrón de archivo deseado en el directorio actual. Necesita saber por dónde empezar, por así decirlo, y ningún archivo coincidente no produce una ruta de inicio.
Si hay al menos un archivo de la extensión deseada, puede usar egrep -ir. find
y xargs
muestra su poder con directorios planos (pero muy grandes) en los que grep falla y calificadores adicionales (por ejemplo, si desea buscar solo archivos .inc, .php y php3). Pero pierde bastante comodidad y velocidad en mi experiencia. Para las declaraciones de clases escritas en humanos, un gran problema será el espacio en blanco. Así que usa egrep en lugar de grep. También LC_ALL = C para velocidad extra. Por conveniencia, a menudo uso:
LC_ALL=C egrep -irn "class[ ]*myclass([ ]|\n)" * | egrep "\.(inc|php[35]?)"
-i -- case insensitive
-r -- recursive for all file pattern (here *)
-n -- include the line number
LC_ALL=C -- search in ASCII, not in utf8, this is much faster.
[ ]* -- match any number of spaces before the class name
([ ]|\n) -- match a space or newline after the classname
Esto todavía puede coincidir con los comentarios, como // class myclass exists in file
, pero creo que son pequeños relativamente, y se pueden filtrar con... | fgrep -v '//'
También puede incluir máscaras de archivos más complejas (por ejemplo, para capturar la mayoría de los archivos .inc y .php) en el patrón de archivo egrep de la siguiente manera:
egrep "pattern" *.[ip]*
Eso (con las primeras opciones) será bastante rápido y se limitará principalmente a los archivos php.
HTH
Sé que dice usar grep
, pero mi favorito personal es usar ack-grep
:
ack-grep "class MyClass"
Esto se ejecuta de forma recursiva, enumera el nombre del archivo en el que encuentra resultados, con números de línea para el lugar donde se encuentran, y resalta. Para apuntar específicamente a archivos php que puede ejecutar:
ack-grep --type-set php:ext:php "path"
El paquete tiene una gran cantidad de opciones; Definitivamente lo recomendaría (y navegar por su página man asociada) para hacer cosas elegantes.
grep -r
no le dio.