2009-05-22 28 views
100

¿Cuál es más eficiente en un gran conjunto de archivos y se debe usar?find -exec cmd {} + vs | xargs

find . -exec cmd {} + 

o

find . | xargs cmd 

(Se supone que no hay caracteres extraños en los nombres de archivo)

+0

Relacionados: https://stackoverflow.com/questions/9612090/how-to-loop-through-file-names-returned-by-find –

Respuesta

94

La diferencia de velocidad será insignificante.

pero hay que asegurarse de que:

  1. Su guión no asumirá que no hay ningún archivo tendrá espacio, tabulación, etc en nombre de archivo; la primera versión es segura, la segunda no.

  2. Su secuencia de comandos no tratará un archivo que comienza con "-" como una opción.

lo tanto, su código debería tener este aspecto:

find . -exec cmd -option1 -option2 -- {} + 

o

find . -print0 | xargs -0 cmd -option1 -option2 -- 

La primera versión es más corto y más fácil de escribir como se puede ignorar 1, pero la segunda versión es más portátil y seguro, ya que "-exec cmd {} +" es una opción relativamente nueva en findutils de GNU (desde 2005, muchos sistemas en ejecución aún no lo tienen) y era buggy recently. Además, muchas personas no conocen este "-exec cmd {} +", como puede ver en otras respuestas.

+4

-print0 es también una opción GNU find (y GNU xargs) que falta de muchos sistemas que no son Linux, por lo que el argumento de portabilidad no es tan válido.Sin embargo, el uso de solo -print y el -0 de xargs, * es * muy portátil. – dannysauer

+4

El punto es que sin -print0 no funciona si hay un archivo con un espacio o pestaña, etc. Esto puede ser una vulnerabilidad de seguridad como si hubiera un nombre de archivo como "foo -o index.html", entonces -o será tratado como una opción. Pruebe en el directorio vacío: "touch - foo \ -o \ index.html; find. | Xargs cat". Obtendrá: "cat: opción no válida - 'o'" – Tometzky

+2

Su ejemplo es un nombre de archivo que contiene un -. Sin -print0, find escupirá ./foo -o index.html. Así que quizás comenzar con un - no es gran cosa, pero el resultado ha cambiado poco, y en un sistema multiusuario, podría proporcionar un vector de ataque si el guión es legible en todo el mundo. – bobpaul

7
find . | xargs cmd 

es más eficiente (se ejecuta cmd el menor número de veces posible, a diferencia de exec, que ejecuta cmd una vez por cada coincidencia). Sin embargo, se encontrará con problemas si los nombres de archivo contienen espacios o caracteres funky.

se sugiere lo siguiente para ser utilizado:

find . -print0 | xargs -0 cmd 

esto funcionará incluso si los nombres de archivo contienen caracteres extraños (-print0 hace find partidos de impresión NUL terminados, -0 hace xargs esperan que este formato.)

+25

Esto no es "find. -exec cmd {} \;" pero "buscar. -exec cmd {} +". Este último no ejecutará un archivo a la vez. – Tometzky

+2

Tenga en cuenta que el enfoque 'xargs' es en realidad significativamente más lento si no hay (o solo unos pocos) archivos coincidentes y' cmd' no tiene mucho que hacer para cada archivo. Por ejemplo, cuando se ejecuta en un directorio vacío, la versión 'xargs' tardará al menos el doble de tiempo, ya que se deben iniciar dos procesos en lugar de solo uno. (Sí, la diferencia es generalmente imperceptible en * nix, pero en un bucle podría ser importante; o, pruébelo en Windows alguna vez ...) – SamB

Cuestiones relacionadas