Uso de punto y coma (;) vs plus (+) con exec en find

¿Por qué hay una diferencia en la producción entre el uso

find . -exec ls '{}' \+ 

y

 find . -exec ls '{}' \; 

Tengo:

 $ find . -exec ls \{\} \+ ./file1 ./file2 .: file1 file2 testdir1 ./testdir1: testdir2 ./testdir1/testdir2: $ find . -exec ls \{\} \; file1 file2 testdir1 testdir2 ./file2 ./file1 

Esto podría ilustrarse mejor con un ejemplo. Digamos que find convierte estos archivos:

 file1 file2 file3 

Usando -exec con un punto y coma ( find . -exec ls '{}' \; ), se ejecutará

 ls file1 ls file2 ls file3 

Pero si usa un signo más en su lugar ( find . -exec ls '{}' \+ ), se pasarán tantos nombres de archivo como sea posible como argumentos a un solo comando:

 ls file1 file2 file3 

El número de nombres de archivo está limitado solo por la longitud máxima de línea de comando del sistema. Si el comando excede esta longitud, el comando se llamará varias veces.

Todas las respuestas hasta ahora son correctas. Ofrezco esto como una demostración más clara (para mí) del comportamiento que se describe utilizando echo lugar de ls :

Con un punto y coma, el comando echo se llama una vez por archivo (u otro objeto del sistema de archivos) encontrado:

 $ find . -name 'test*' -exec echo {} \; ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

Con un más, el comando echo se llama solo una vez. Cada archivo encontrado se pasa como un argumento.

 $ find . -name 'test*' -exec echo {} \+ ./test.c ./test.cpp ./test.new ./test.php ./test.py ./test.sh 

Si find un gran número de resultados, puede encontrar que el comando al que se llama ahoga la cantidad de argumentos.

del hombre

-exec comando;

Ejecutar comando; verdadero si se devuelve 0 estado. Todos los siguientes argumentos para encontrar se toman como argumentos para el comando hasta que un argumento que consta de ‘;’ se encuentra. La cadena ‘{}’ se reemplaza por el nombre del archivo actual que se procesa en todas partes en los argumentos del comando, no solo en los argumentos donde está solo, como en algunas versiones de find. Es posible que ambas construcciones deban escaparse (con un ‘\’) o citarse para protegerlas de la expansión del shell. Consulte la sección EJEMPLOS para ver ejemplos del uso de la opción ‘-exec’. El comando especificado se ejecuta una vez para cada archivo coincidente. El comando se ejecuta en el directorio de inicio. Hay problemas de seguridad inevitables que rodean el uso de la opción -exec; deberías usar la opción -execdir en su lugar.

-exec comando {} +

Esta variante de la opción -exec ejecuta el comando especificado en los archivos seleccionados, pero la línea de comando se construye al agregar cada nombre de archivo seleccionado al final; el número total de invocaciones del comando será mucho menor que el número de archivos coincidentes. La línea de comando está construida de la misma manera que xargs construye sus líneas de comando. Solo se permite una instancia de ‘{}’ dentro del comando. El comando se ejecuta en el directorio de inicio.

así que la entiendo, \; ejecuta comandos separados y + agrega cada nombre. es básicamente la forma en que se ejecuta, ya que el \ es un escape por lo que es

 ls testdir1; ls testdir2 

vs

 ls testdir1 testdir2 

haciendo lo anterior en mi caparazón reflejó el resultado de su pregunta.

ACTUALIZACIÓN 2

Entonces, ¿por qué querrías usar +

decir que tengo dos archivos 1.tmp y 2.tmp

1.tmp :

1
2
3

2.tmp :

0
2
3

corriendo

  find *.tmp -exec diff {} \; > diff: missing operand after `1.tmp' > diff: Try `diff --help' for more information. > diff: missing operand after `2.tmp' > diff: Try `diff --help' for more information. 

donde si usa + y concatena el hallazgo resultados como sigue:

 find *.tmp -exec diff {} \+ 1c1,3 < 1 --- > 0 > 2 > 30 

entonces en este caso es la diferencia entre diff 1.tmp; diff 2.tmp y diff 1.tmp 2.tmp

Hay casos donde \; es apropiado y + será necesario. usar + con rm es una de esas instancias, en la que si está eliminando una gran cantidad de archivos, la velocidad se ha mejorado mucho; Siempre me gusta aprender más sobre Find, es una herramienta tan poderosa y útil. Espero que esto sea suficiente para explicar las diferencias.

Este es el trato: find tiene una syntax especial. Usas el {} tal como es porque tienen un significado para encontrar como la ruta del archivo encontrado y (la mayoría) las conchas no las interpretan de otro modo. Necesitas la barra invertida \; porque el punto y coma tiene un significado para el caparazón, que se lo come antes de que el hallazgo pueda obtenerlo. Entonces, lo que find quiere ver DESPUÉS de que se complete el shell, en la lista de argumentos pasada al progtwig C, es

“-exec”, “rm”, “{}”, “;”

pero necesitas \; en la línea de comando para obtener un punto y coma a través del intérprete de comandos a los argumentos.

Puedes salir con \{\} porque la interpretación de \{\} citada en el intérprete de comandos es solo {} . Del mismo modo, podría usar ‘{}’.

Lo que no puedes hacer es usar

  -exec 'rm {} ;' 

porque el intérprete de comandos lo interpreta como un argumento,

“-exec”, “rm {};”

y “rm {};” no es el nombre de un comando. (Al menos, a menos que alguien esté realmente jodiendo).

Actualizar

la diferencia es entre

 $ ls file1 $ ls file2 

y

 $ ls file1 file2 

El + está cateando los nombres en una línea de comando.

La diferencia entre ; (punto y coma) o + (signo más) es la forma en que los argumentos se pasan al parámetro -execdir -exec / -execdir . Por ejemplo:

  • usar ; ejecutará múltiples comandos (por separado para cada argumento),

    Ejemplo:

     $ find /etc/rc* -exec echo Arg: {} ';' Arg: /etc/rc.common Arg: /etc/rc.common~previous Arg: /etc/rc.local Arg: /etc/rc.netboot 

    Todos los argumentos siguientes para find se toman como argumentos para el comando.

    La cadena {} se reemplaza por el nombre del archivo actual que se está procesando.

  • el uso de + ejecutará los comandos menos posibles (ya que los argumentos se combinan juntos). Es muy similar a cómo funciona el comando xargs , por lo que usará tantos argumentos por comando como sea posible para evitar exceder el límite máximo de argumentos por línea.

    Ejemplo:

     $ find /etc/rc* -exec echo Arg: {} '+' Arg: /etc/rc.common /etc/rc.common~previous /etc/rc.local /etc/rc.netboot 

    La línea de comando se construye al agregar cada nombre de archivo seleccionado al final.

    Solo se permite una instancia de {} dentro del comando.

Ver también:

  • man find
  • Usar punto y coma (;) vs plus (+) con exec en find at SO
  • Comando simple de Unix, ¿cuál es el {} y \; para en SO
  • ¿Qué significa {} + en el comando find -exec? en Unix

estábamos tratando de encontrar el archivo para la limpieza.

encontrar . -exec echo {} \; comando funcionó durante la noche al final no hay resultados.

encontrar . -exec echo {} \ + tienen resultados y solo le tomaron unas horas.

Espero que esto ayude.