¿Cuál es la mejor manera de contar los resultados de "búsqueda"?
99
Mi solución actual sería find <expr> -exec printf '.' \; | wc -c, pero esto lleva demasiado tiempo cuando hay más de 10000 resultados. ¿No hay una forma mejor o más rápida de hacer esto?
No es más confiable si la marca -printf para buscar no es compatible con su plataforma. ;-)
Randy Howard
7
Tenga en cuenta que puede reducir algunos nanosegundos más sin citar el punto en-printf '.'
Jens
6
@Jens - especialmente cuando se tiene en cuenta el tiempo que se tarda en escribir eso
Brian Agnew
6
Con un punto de referencia tan pequeño, los tiempos probablemente estén dominados por otros factores además de lo que desea medir. Un experimento con un árbol grande sería más útil. Pero esto tiene mi voto para hacer realmente lo que pidió el OP.
tripleee
133
Por qué no
find <expr>| wc -l
como una simple solución portátil? Su solución original está generando un nuevo procesoprintf para cada archivo individual encontrado, y eso es muy costoso (como acaba de descubrir).
Tenga en cuenta que esto contará en exceso si tiene nombres de archivo con nuevas líneas incrustadas, pero si tiene eso, sospecho que sus problemas son un poco más profundos.
-1: se romperá en el archivo con nuevas líneas, y es más lento que contar bytes =)
Gilles Quenot
21
No creo que eso justifique un voto negativo dado que la limitación de nombre de archivo / nueva línea es bastante rara y se indicó anteriormente. Más lento ? Quizás. Dado que está consultando un sistema de archivos, sospecho que la diferencia de velocidad es pequeña. En mis 10,000 archivos mido una diferencia de 3 ms
Brian Agnew
8
La diferencia de rendimiento entre 'find <expr> | wc -l' y 'find <expr> -printf. | wc -c 'son extremadamente pequeños. El almacenamiento en caché (es decir, si ejecuta la misma búsqueda dos veces sobre el mismo árbol) es mucho más importante. En mi humilde opinión, la solución con "wc -l" es mucho más intuitiva.
pitseeker
4
Esta es mi countfilesfunción en mi ~/.bashrc(es razonablemente rápida, debería funcionar para Linux y FreeBSD find, y no se deja engañar por las rutas de archivo que contienen caracteres de nueva línea; la final wcsolo cuenta bytes NUL):
Esta solución es ciertamente más lenta que algunas de las otras find -> wcsoluciones aquí, pero si estuviera dispuesto a hacer algo más con los nombres de los archivos además de contarlos, podría hacerlo readdesde la findsalida.
n=0while read -r -d '';do((n++))# count# maybe perform another act on filedone<<(find <expr>-print0)
echo $n
Es solo una modificación de una solución que se encuentra en BashGuide que maneja correctamente archivos con nombres no estándar al hacer que el finddelimitador de salida sea un byte NUL usando print0y leyéndolo usando ''(byte NUL) como delimitador de bucle.
Respuestas:
Intente esto en su lugar (requiera
find
el-printf
soporte):Será más confiable y rápido que contar las líneas.
Tenga en cuenta que utilizo
find
'sprintf
, no un comando externo.Hagamos la banca un poco:
Mi punto de referencia de fragmentos:
Con líneas completas:
Entonces mi solución es más rápida =) (la parte importante es la
real
línea)fuente
-printf '.'
Por qué no
como una simple solución portátil? Su solución original está generando un nuevo proceso
printf
para cada archivo individual encontrado, y eso es muy costoso (como acaba de descubrir).Tenga en cuenta que esto contará en exceso si tiene nombres de archivo con nuevas líneas incrustadas, pero si tiene eso, sospecho que sus problemas son un poco más profundos.
fuente
Esta es mi
countfiles
función en mi~/.bashrc
(es razonablemente rápida, debería funcionar para Linux y FreeBSDfind
, y no se deja engañar por las rutas de archivo que contienen caracteres de nueva línea; la finalwc
solo cuenta bytes NUL):fuente
Esta solución es ciertamente más lenta que algunas de las otras
find -> wc
soluciones aquí, pero si estuviera dispuesto a hacer algo más con los nombres de los archivos además de contarlos, podría hacerloread
desde lafind
salida.Es solo una modificación de una solución que se encuentra en BashGuide que maneja correctamente archivos con nombres no estándar al hacer que el
find
delimitador de salida sea un byte NUL usandoprint0
y leyéndolo usando''
(byte NUL) como delimitador de bucle.fuente