Probé ambos comandos y el comando   find | grep 'filename'  es muchas veces más lento que el find 'filename'  comando simple .
¿Cuál sería una explicación adecuada para este comportamiento?
                    
                        command-line
                                grep
                                find
                                search
                                file-search
                                
                    
                    
                        yoyo_fun
fuente
                
                fuente

time find "$HOME" -name '.profile'informa más tiempo quetime find "$HOME" | grep -F '.profile'. (17s vs 12s).grepvariación coincidirá en cualquier parte delfindresultado, mientras que la coincidencia confind -namesolo coincidirá exactamente (en este caso).find filenamesería rápida . Asumí que se trataba de un error tipográfico y que el OP significabafind -name filename. Confind filename, solofilenamesería examinado (y nada más).Respuestas:
(Estoy asumiendo GNU
findaquí)Usando solo
sería rápido, porque simplemente regresaría
filename, o los nombres dentrofilenamesi es un directorio, o un error si ese nombre no existiera en el directorio actual. Es una operación muy rápida, similar als filename(pero recursiva sifilenamees un directorio).A diferencia de,
permitiría
findgenerar una lista de todos los nombres del directorio actual y debajo, quegrepluego se filtraría. Obviamente, esta sería una operación mucho más lenta.Supongo que lo que realmente se pretendía era
Esto buscaría
filenamecomo 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 lagrepsolución coincidiríafilenamecon la ruta completa de cada nombre encontrado, de manera similar a lo-path '*filename*'que haría confind.La confusión proviene de un malentendido de cómo
findfunciona.La utilidad toma varias rutas y devuelve todos los nombres debajo de estas rutas.
Luego, puede restringir los nombres devueltos utilizando varias pruebas que pueden actuar sobre el nombre del archivo, la ruta, la marca de tiempo, el tamaño del archivo, el tipo de archivo, etc.
Cuando tu dices
solicita
findenumerar cada nombre disponible bajo las tres rutasa,byc. 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
Esto genera una lista de todos los nombres en el directorio actual (
.) y 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 a los nombres que coinciden con elfilenameuso-name 'filename'. La cadenafilenamepuede ser un patrón global de nombre de archivo, como*.txt(¡solo recuerde citarlo!).Ejemplo:
Lo siguiente parece "encontrar" el archivo llamado
.profileen mi directorio de inicio:Pero, de hecho, solo devuelve todos los nombres en la ruta
.profile(solo hay un nombre, y ese es el de este archivo).Luego
cdsubo un nivel e intento nuevamente:El
findcomando 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í:fuente
find filenamevolvería solofilenamesifilenameno fuera del directorio de tipos (o fuera del directorio de tipos, pero no tuviera ninguna entrada en sí)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.
fuente
find jackenumerarájacksi es un archivo llamadojack, o todos los nombres en el directorio si es un directorio. Es un malentendido de cómofindfunciona.Todavía no he entendido el problema, pero puedo proporcionar algunas ideas más.
Al igual que para Kusalananda, la
find | grepllamada 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 quefindpuede 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 escriban en la consola puedan ejecutarse en paralelo (lo que,findcomo un proceso de un solo hilo, no puede hacer por sí solo.Es
findculpaComparando las dos llamadas
y
muestra que
findhace algo increíblemente estúpido (sea lo que sea). Simplemente resulta ser bastante incompetente en la ejecución-name '*.txt'.Puede depender de la relación entrada / salida
Puede pensar que
find -namegana si hay muy poco que escribir. Pero esto solo se vuelve más vergonzosofind. Pierde incluso si no hay nada para escribir en contra de los archivos de 200K (13M de datos de tubería) paragrep:findgrepaunque puede ser tan rápido comoResulta que
findla estupidez connameno se extiende a otras pruebas. Use una expresión regular en su lugar y el problema desaparecerá: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
fuente
-nameprueba primero, es posible que haya sido más lenta debido a que el contenido del directorio no está en caché. (Cuando se prueba-namey-regexme parece que tienen más o menos el mismo tiempo, al menos una vez el efecto de caché se ha tomado en consideración Por supuesto que sólo puede ser una versión diferente de.find...)findversión es find (GNU findutils) 4.6.0-name '*.txt'ralenticefind? Tiene que hacer un trabajo extra, probando cada nombre de archivo.findtiene que escribir menos datos. Y escribir en una tubería es una operación mucho más lenta./dev/nullalguna manera usó menos tiempo del sistema.Aviso : supondré que te refieres
find . -name filename(de lo contrario, estás buscando cosas diferentes; enfind filenamerealidad 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 una estructura de árbol , lo que permite localizar rápidamente cualquier archivo.
Cuando se pregunta
finda localizar un archivo cuyo nombre sólo requiere la comprobación,findse pida para que el archivo, y sólo ese archivo, el sistema de archivos subyacente, que leerá muy pocas páginas de la memoria de masa. Entonces, si el sistema de archivos vale la pena, esta operación se ejecutará mucho más rápido que atravesar todo el árbol para recuperar todas las entradas.findSin embargo, cuando pides algo simple, eso es exactamente lo que haces, atraviesas todo el árbol y lees. 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).fuente
Supongamos que el archivo / john / paul / george / ringo / beatles existe y el archivo que está buscando se llama 'piedras'
find comparará "beatles" con "piedras" y lo soltará cuando la "s" y la "b" no coincidan.
En este caso, find pasará '/ john / paul / george / ringo / beatles' a grep y grep tendrá que abrirse camino a través de todo el camino antes de determinar si es una coincidencia.
grep está haciendo mucho más trabajo, por lo que lleva más tiempo
fuente