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).grep
variación coincidirá en cualquier parte delfind
resultado, mientras que la coincidencia confind -name
solo coincidirá exactamente (en este caso).find filename
sería rápida . Asumí que se trataba de un error tipográfico y que el OP significabafind -name filename
. Confind filename
, solofilename
sería examinado (y nada más).Respuestas:
(Estoy asumiendo GNU
find
aquí)Usando solo
sería rápido, porque simplemente regresaría
filename
, o los nombres dentrofilename
si 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 sifilename
es un directorio).A diferencia de,
permitiría
find
generar una lista de todos los nombres del directorio actual y debajo, quegrep
luego 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
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 lagrep
solución coincidiríafilename
con 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
find
funciona.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
find
enumerar cada nombre disponible bajo las tres rutasa
,b
yc
. 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 elfilename
uso-name 'filename'
. La cadenafilename
puede ser un patrón global de nombre de archivo, como*.txt
(¡solo recuerde citarlo!).Ejemplo:
Lo siguiente parece "encontrar" el archivo llamado
.profile
en 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
cd
subo un nivel e intento nuevamente:El
find
comando 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 filename
volvería solofilename
sifilename
no 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 jack
enumerarájack
si es un archivo llamadojack
, o todos los nombres en el directorio si es un directorio. Es un malentendido de cómofind
funciona.Todavía no he entendido el problema, pero puedo proporcionar algunas ideas más.
Al igual que para Kusalananda, la
find | grep
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 quefind
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 escriban en la consola puedan ejecutarse en paralelo (lo que,find
como un proceso de un solo hilo, no puede hacer por sí solo.Es
find
culpaComparando las dos llamadas
y
muestra que
find
hace 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 -name
gana 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
:find
grep
aunque puede ser tan rápido comoResulta que
find
la estupidez conname
no 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
-name
prueba primero, es posible que haya sido más lenta debido a que el contenido del directorio no está en caché. (Cuando se prueba-name
y-regex
me 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
...)find
versión es find (GNU findutils) 4.6.0-name '*.txt'
ralenticefind
? Tiene que hacer un trabajo extra, probando cada nombre de archivo.find
tiene que escribir menos datos. Y escribir en una tubería es una operación mucho más lenta./dev/null
alguna manera usó menos tiempo del sistema.Aviso : supondré que te refieres
find . -name filename
(de lo contrario, estás buscando cosas diferentes; enfind filename
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 una estructura de árbol , lo que permite localizar rápidamente cualquier archivo.
Cuando se pregunta
find
a localizar un archivo cuyo nombre sólo requiere la comprobación,find
se 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.find
Sin 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