¿Cómo funciona este comando de búsqueda usando "find... -exec sh -c '...' sh {} +"?

¿Cómo funciona este comando de búsqueda usando "find... -exec sh -c '...' sh {} +"?

@StephaneChazelas publicó la siguiente solución a esta pregunta y respuesta:Tener algunos problemas al usar "find -exec {} +".

$ find . -iname "*.extension" -exec sh -c '
  exec <command> "$@" <additional parameters>' sh {} +

Qué está pasando aquí? ¿Qué hace específicamente el último sh {}? Parece como si simplemente estuviera ahí para apaciguar -execel comando de búsqueda para que tenga algo que hacer, un NOOP.

Podría colocarlo echo {}allí con la misma facilidad y parece funcionar bien.

Respuesta1

La sintaxis es:

find ... -exec cmd {} +

findencontrará una cantidad de archivos según los criterios ...y los ejecutará cmdcon esa lista de rutas de archivos como argumentos, tantos como sea posible sin superar el límite de tamaño de los argumentos de un comando.

Si es necesario, puede dividir la lista de archivos y llamar cmdvarias veces. Por ejemplo, puede terminar llamando:

cmd ./file1 ./file2 ... ./file3000
cmd ./file3001 ./file3002 ... ./file4321

Una limitación es que {}tiene que ser el último. No puedes, por ejemplo, escribir:

find ... -exec cmd {} other args +

como podrías hacerlo con ';'en lugar de '+'.

Puedes escribir:

find ... -exec echo foo {} +

pero no:

find ... -exec echo {} foo +

Por lo tanto, si necesita agregar algunos argumentos adicionales cmddespués de la lista de archivos, debe recurrir a llamar a un shell. (Otras razones por las que necesitaría llamar a un Shell serían cada vez que necesite usar una función de Shell como redirecciones, canalizaciones, algunas expansiones de cadenas...)

En sh -c 'inline-script' x a b c, para inline-script, $0es x, $1es a, $2es b... también "$@"está la lista de esos 3 argumentos: a, b y c. Entonces en:

find ... -exec sh -c 'cmd "$@" other arg' find-sh {} +

Para elguión en línea, $0(que se usa, por ejemplo, cuando se muestran mensajes de error) está configurado find-shy "$@"es la lista de archivos (a lo que findse expande {}).

Usando la execfunción especial incorporada del shell:

find ... -exec sh -c 'exec cmd "$@" other arg' find-sh {} +

Le decimos al shell que no bifurque un proceso adicional para ejecutarlo cmd, sino que lo ejecute en el mismo proceso (reemplazando el proceso del shell en ejecución con ese comando). A algunos shells les gustan zshy algunas implementaciones kshlo hacen implícitamente para el último comando en un script en línea (también bashcuando solo hay un comando en el script en línea como aquí).

información relacionada