@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 -exec
el 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 {} +
find
encontrará una cantidad de archivos según los criterios ...
y los ejecutará cmd
con 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 cmd
varias 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 cmd
despué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
, $0
es x
, $1
es a
, $2
es 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-sh
y "$@"
es la lista de archivos (a lo que find
se expande {}
).
Usando la exec
funció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 zsh
y algunas implementaciones ksh
lo hacen implícitamente para el último comando en un script en línea (también bash
cuando solo hay un comando en el script en línea como aquí).