desarrollo-web-br-bd.com

¿Por qué el comando "find | grep 'filename'" es mucho más lento que "find 'filename'"?

Intenté ambos comandos y el comando find | grep 'filename' es muchas veces más lento que el simple find 'filename' comando.

¿Cuál sería una explicación adecuada para este comportamiento?

10
yoyo_fun

(Asumo GNU find aquí)

Usando solo

find filename

would sería rápido, porque solo devolvería filename, o los nombres dentro de filename si es un directorio, o un error si ese nombre no existía en el actual directorio. Es una operación muy rápida, similar a ls filename (pero recursivo si filename es un directorio).

A diferencia de,

find | grep filename

permitiría a find generar una lista de todos nombres del directorio actual e inferior, que grep luego filtraría. Obviamente, esta sería una operación mucho más lenta.

Supongo que lo que en realidad fue

find . -type f -name 'filename'

Esto buscaría filename como el nombre de un archivo normal en cualquier parte del directorio actual o debajo.

Esto será tan rápido (o comparativamente rápido) como find | grep filename, pero la solución grep haría coincidir filename con la ruta completa de cada nombre encontrado, de manera similar a lo que -path '*filename*' haría con find.


La confusión proviene de un malentendido sobre cómo funciona find.

La utilidad toma un número de rutas y devuelve todos los nombres debajo de estas rutas.

Entonces puede restringir los nombres devueltos utilizando varias pruebas que pueden actuar sobre el nombre de archivo, la ruta, la marca de tiempo, el tamaño del archivo, el tipo de archivo, etc.

Cuando tu dices

find a b c

le pide a find que enumere todos los nombres disponibles en las tres rutas a, b y c. Si se trata de nombres de archivos normales en el directorio actual, se devolverán. Si alguno de ellos es el nombre de un directorio, se devolverá junto con todos los demás nombres dentro de ese directorio.

Cuando lo hago

find . -type f -name 'filename'

Esto genera una lista de todos los nombres en el directorio actual (.) y por debajo. Luego, restringe los nombres a los de los archivos normales, es decir, no a directorios, etc., con -type f. Luego hay una restricción adicional para los nombres que coinciden con filename usando -name 'filename'. La cadena filename puede ser un patrón global de nombre de archivo, como *.txt (¡solo recuerda citarlo!).

Ejemplo:

Lo siguiente parece "encontrar" el archivo llamado .profile en mi directorio de inicio:

$ pwd
/home/kk
$ find .profile
.profile

Pero, de hecho, solo devuelve todos los nombres en la ruta .profile (solo hay un nombre, y ese es el de este archivo).

Luego, cd subo un nivel e intento nuevamente:

$ cd ..
$ pwd
/home
$ find .profile
find: .profile: No such file or directory

El comando find ahora no puede encontrar ninguna ruta llamada .profile.

Sin embargo, si consigo que mire el directorio actual, y luego restrinja los nombres devueltos a solo .profile, también lo encuentra desde allí:

$ pwd
/home
$ find . -name '.profile'
./kk/.profile
11
Kusalananda

Explicación no técnica: Buscar a Jack en una multitud es más rápido que buscar a todos en una multitud y eliminar a todos de consideración excepto a Jack.

2
S Renalds

Todavía no he entendido el problema, pero puedo proporcionar algunas ideas más.

Al igual que para Kusalananda el find | grep la llamada es claramente más rápida en mi sistema, lo que no tiene mucho sentido. Al principio asumí algún tipo de problema de amortiguación; que escribir en la consola ralentiza el tiempo hasta la próxima llamada al sistema para leer el siguiente nombre de archivo. Escribir en una tubería es muy rápido: aproximadamente 40MiB/s incluso para escrituras de 32 bytes (en mi sistema bastante lento; 300 MiB/s para un tamaño de bloque de 1MiB). Por lo tanto, supuse que find puede leer del sistema de archivos más rápido al escribir en una tubería (o archivo) para que las dos operaciones que leen las rutas de los archivos y escriben en la consola puedan ejecutarse en paralelo (que find como un proceso de subproceso único no puede hacerlo por sí solo.

Es culpa de find

Comparando las dos llamadas

:> time find "$HOME"/ -name '*.txt' >/dev/null

real    0m0.965s
user    0m0.532s
sys     0m0.423s

y

:> time find "$HOME"/ >/dev/null

real    0m0.653s
user    0m0.242s
sys     0m0.405s

muestra que find hace algo increíblemente estúpido (sea lo que sea). Simplemente resulta ser bastante incompetente para ejecutar -name '*.txt'.

Puede depender de la relación entrada/salida

Se podría pensar que find -name gana si hay muy poco que escribir. Pero esto solo se vuelve más vergonzoso para find. Pierde incluso si no hay nada que escribir en contra de archivos de 200K (13M de datos de tubería) para grep:

time find /usr -name lwevhewoivhol

find puede ser tan rápido como grep, aunque

Resulta que la estupidez de find con name no se extiende a otras pruebas. Use una expresión regular en su lugar y el problema desaparecerá:

:> time find "$HOME"/ -regex '\.txt$' >/dev/null     

real    0m0.679s
user    0m0.264s
sys     0m0.410s

Supongo que esto puede considerarse un error. ¿Alguien dispuesto a presentar un informe de error? Mi versión es find (GNU findutils) 4.6.0

1
Hauke Laging

Aviso : Asumo que te refieres a find . -name filename (de lo contrario, estás buscando cosas diferentes; find filename en realidad busca en una ruta llamada ¡nombre de archivo, que puede contener casi ningún archivo, por lo que sale muy rápido).


Supongamos que tiene un directorio que contiene cinco mil archivos. En la mayoría de los sistemas de archivos, estos archivos se almacenan en un árbol estructura , que permite localizar rápidamente cualquier archivo dado.

Entonces, cuando le pide a find que ubique un archivo cuyo nombre solo requiere verificación, find will ask for that file, y ese archivo solamente, al sistema de archivos subyacente, que leerá muy pocas páginas del almacenamiento masivo. Entonces, si el sistema de archivos vale la pena, esta operación se ejecutará mucho más rápido que atravesando todo el árbol para recuperar todas las entradas.

Cuando pides un simple find sin embargo, eso es exactamente lo que haces, atraviesas todo el árbol, leyendo. Cada. Soltero. Entrada. Con directorios grandes, esto podría ser un problema (es exactamente la razón por la cual varios softwares, que necesitan almacenar muchos archivos en el disco, crearán "árboles de directorio" de dos o tres componentes de profundidad: de esta manera, cada hoja solo necesita contener menos archivos).

0
LSerni