Tengo problemas para buscar en TODOS los directorios a la vez con grep
. Cuando uso el comando:
find . -name "*.txt" | xargs grep texthere
Simplemente toma una eternidad y luego me da el error "no existe tal archivo o directorio".
¿Por qué sucede esto? ¿No hay nada más fácil que hacerlo grep
? ¿O estoy usando el comando incorrecto?
Respuesta1
Si tiene GNU grep, el propio grep admite la opción "-r" para buscar recursivamente, como lo sugiere @Ouroborus.
Si desafortunadamente su grep no admite dicha opción, como en SunOS, puede usar los siguientes comandos:
find . -name "*.txt" -exec grep -n your_pattern {} /dev/null \;
El truco se /dev/null
agrega para garantizar que cada ejecución de grep tenga dos archivos (el archivo que coincide con *.txt y /dev/null) proporcionados, lo que lo obliga a imprimir el nombre de los archivos que se buscan. Y puede agregar -type f
la opción de find
para refinar el alcance de find
.
Respuesta2
Como enesta respuesta, probablemente estés mejor con:
grep -rnw '/path/to/somewhere/' -e "pattern"
-r
o-R
es recursivo,-n
es el número de línea, y-w
los soportes coinciden con toda la palabra.-l
(L minúscula) se puede agregar para proporcionar solo el nombre de los archivos coincidentes.
Respuesta3
Si recibe errores sobre los permisos (no dice que los tenga), entonces supongo que se encuentra en el directorio raíz ( /
) o en alguna ruta donde no tiene permiso para leer todos los archivos. como en /etc
o en /var
. Pero como usted dice que lleva muchísimo tiempo, me inclino más por la primera suposición (el directorio raíz).
Si quieres buscar absolutamentetodoarchivos en elenterosistema, que lo que estás haciendo es bastante correcto. ÉlvoluntadToma mucho tiempo sin importar lo que hagas. Es simplemente una enorme cantidad de archivos para buscar.
Puede utilizar find
para limitar la cantidad de archivos a ver.
Por el momento tienes
$ find . -name "*.txt" | xargs grep texthere
Como parece que solo le interesan los archivos de texto sin formato, podemos excluir cualquier otro tipo de archivo (ejecutables):
$ find / -type f \! -perm -o=x -name "*.txt" | xargs grep texthere
lo reemplacé .
con/
aquí, porque ahí es dondepensarlo eres (corrígeme si me equivoco). También estoy especificando que quieroarchivos(-type f
) que sonno ejecutable( \! -perm -o=x
) (es !
necesario escapar para que su caparazón no haga cosas raras con él).
Ahora, hay un par de cosas más que podemos hacer. Una es una cuestión de seguridad y la otra puedeposiblementeMejorar un poquito la velocidad.
Algunos nombres de archivos pueden tener espacios u otros caracteres extraños que normalmente no queremos en los nombres de archivos. Para poder pasarlos correctamente entre nosotros find
y lo hacemosgrep
$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 grep texthere
Esto ( -print0
) significa que cada nombre de archivo estará delimitado por un nul
carácter ( \0
) en lugar de un espacio. Y la opción correspondiente para xargs
recibir estos nul
nombres de archivos delimitados es -0
.
Es porque no estás usando esas dos opciones que creo que obtienes esos errores de "no existe tal archivo o directorio".
Lo de la velocidad es fgrep
. Esta es una utilidad que es exactamente equivalente a grep -F
la que debería usar si su cadena de búsqueda es una cadena de texto sin formato sin expresiones regulares.
Entonces, si tiene una cadena de texto sin formato y desea buscarla en cada archivo de todo el sistema:
$ find / -type f \! -perm -o=x -name "*.txt" -print0 | xargs -0 fgrep texthere
Lo del permiso... Obviamente habrá archivos que no podrás leer. Puede ejecutar find
y fgrep
anteponerles sudo
:
$ sudo find ... | xargs -0 sudo fgrep texthere
O podría intentar crear otra -perm
bandera find
(y también hacer que ignore los directorios a los que no puede ingresar), pero eso consumiría demasiado tiempo y resultaría en una línea de comando ridículamente larga, así que no haré eso aquí.
O podría simplemente sudo -s
obtener un shell raíz y ejecutarlo desde allí... pero generalmente lo desaconsejaría porque la gente tiende a estropear sus sistemas al olvidar que están root
.
OTRA SOLUCIÓNSería utilizar el locate
comando para localizar todos los .txt
archivos en todo el sistema. Ellocate
comando no busca en la jerarquía de archivos sino que utiliza una base de datos (que generalmente se actualiza diariamente, por lo que notodolos archivos pueden estar allí). La base de datos sólo contiene archivos en directorios accesibles para todos los usuarios, por lo que si ha eliminado los permisos de lectura en sus propios directorios, sus archivos no estarán allí.
Entonces, reemplazando el find
comando anterior con el locate
casi equivalente:
$ locate '*.txt' -0 | xargs -0 fgrep texthere
La -0
opción (o --null
en algunos sistemas) corresponde a la --print0
opción de find
.