¿Encontrar una subcadena en archivos en subdirectorios con un solo comando incorporado?

10

En Windows, si quisiera encontrar una cadena en todos los archivos en todos los subdirectorios, haría algo como

findstr /C:"the string" /S *.h

Sin embargo, en Linux (por ejemplo, Ubuntu) no he encontrado ninguna otra manera que algún comando canalizado la participación find, xargsy grep(un ejemplo es en esta página: ? ¿Cómo puedo recurrentemente grep a través de subdirectorios ). Sin embargo, mi pregunta es diferente: ¿hay algún comando único incorporado que funcione a través de esta magia, sin tener que escribir mi script de shell?

Guido Domenici
fuente

Respuestas:

19

GNU grep permite la búsqueda recursiva a través de subdirectorios:

grep -r --include='*.h' 'the string' .
meneo
fuente
Probé esta línea de comando exacta en Ubuntu pero obtengo "grep: opción no válida - 'M'" aunque no puedo ver ninguna 'M' en ningún lado ... desconcertante
Guido Domenici
@Guido funciona bien aquí
phunehehe
En una edición sugerida, TomasG recomienda cambiar el último *a '*': "Es necesario citar el último comodín para evitar errores cuando algún nombre de archivo comienza con -"
Michael Mrozek
En un extraño giro de los acontecimientos, ahora también funciona para mí, como se ingresó en la respuesta original. ¡Gracias!
Guido Domenici
1
@Guido: Su problema puede deberse a un archivo en el directorio actual llamado -Msomething, o a una GREP_OPTIONSconfiguración.
Gilles 'SO- deja de ser malvado'
2

grep -r searchpattern /path/to/start/in

Donde /path/to/start/in/puede ser solo " ." para el directorio actual.

mattdm
fuente
1

No. find -name \*.h -print0 | xargs -0 grep -l 'the regex'es tan mágico como se pone.

Glenn Jackman
fuente
GNU grep tiene los casos comunes integrados con su -ropción. No hay necesidad de artillería pesada.
Gilles 'SO- deja de ser malvado'
3
xargsagrega solo ruido. Usofind -name \*.h -execdir grep -l 'the regex {} +
usuario desconocido el
0

¿Hay algún comando incorporado que funcione a través de esta magia ...?

Para ser pedante, no, no puedes asumir que tal orden existe .

Hay muchas implementaciones diferentes de Unix, y cada una tiene sus peculiaridades diferentes. POSIX, el denominador común (y lo más parecido a un estándar en Unices) no especifica dicha opción paragrep .

Como se mencionó en otras respuestas, la implementación de GNU greptiene una opción no estándar que hace lo que usted desea. Si bien esta implementación particular puede ser común en los sistemas Linux, no puede asumir su disponibilidad en ningún Unix, incluso en algunos sistemas Linux.

Finalmente, debo mencionar que es la filosofía de Unix favorecer la combinación de varios programas primitivos, sobre el uso de un gran ejecutable monolítico que intenta hacer todo de una vez.

En su caso, rastrear el sistema de archivos y combinar expresiones regulares en una secuencia son dos tareas separadas. Es normal tratar cada uno en un programa separado.

rahmu
fuente
0

Para encontrar una cadena del directorio dado, use el siguiente comando

find <fullDirectoryPath> -name '*' -exec grep -l '<StringToFind>' {} \;

Por ejemplo:

find /apps_bev/apps/xfer/export/02210 -name '*' -exec grep -l '38221000001032' {} \;
Yogesh
fuente
1
greppuede tomar más de un archivo como argumentos, por lo que debe usarlo en +lugar de \;evitar ejecutar una grepinvocación por archivo que es bastante ineficiente.
Stéphane Chazelas
1
Tenga en cuenta que se -name '*'restringe a los archivos cuyo nombre es texto válido en la configuración regional actual ( findal menos en algunas implementaciones), pero los otros componentes del directorio aún pueden contener secuencias de bytes que no forman caracteres válidos. Si su intención con eso -name '*'era asegurarse de que la salida es texto válido (al omitir los archivos con nombres incorrectos), preferiría usar find ... ! -name '*' -prune -o -exec grep ... {} +, que también evitaría finddescender a directorios con nombres incorrectos.
Stéphane Chazelas