¿Por qué 'find -exec cmd {} +' debe terminar en '{} +'?

11

Prefacio: entiendo la diferencia entre -exec {} \;& -exec {} +. Tampoco tengo un problema como tal , solo tengo curiosidad por la semántica de find.


Al finalizar el -execargumento con en +lugar de ;, necesitamos terminar esto con {} +, por ejemplo:

# FreeBSD find
$ find . -type f -exec cp {} /tmp +
find: -exec: no terminating ";" or "+"

# GNU find is even more cryptic:
$ find: missing argument to `-exec'

Usar ;en estos ejemplos en lugar de +funciona bien (pero obviamente hace algo más).

Desde POSIX :

-exec utility_name [argument ...] ;
-exec utility_name [argument ...] {} +

... Solo un <plus-sign> que sigue inmediatamente a un argumento que contiene solo los dos caracteres " {}" debe puntuar el final de la expresión primaria. Otros usos del <plus-sign> no se tratarán como especiales.

En otras palabras, cuando se usa +, el comando debe terminar con {} +.

¿Por qué es esto? ¿Y por qué solo con el +y no con el ;? Al principio pensé que tal vez evitaría conflictos con los nombres de archivo que contienen un +, pero ¿los nombres de archivo con un ;parecen funcionar bien? Me resulta difícil creer que esta limitación sea arbitraria ...

Martin Tournoij
fuente
3
FWIW, la página POSIX también dice que The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210y en ese documento encontrará más detalles, por ejemplo:Note that the "+" is only treated as special if it immediately follows "{}". This minimises the chances of causing problems with existing uses of "+" as an argument with "-exec".
don_crissti

Respuestas:

5

La justificación dada en la especificación POSIX es:

La "-exec ... {} +"sintaxis adoptada fue el resultado de la Interpretación IEEE PASC 1003.2 # 210. Cabe señalar que este es un cambio incompatible con el estándar ISO / IEC 9899: 1999. Por ejemplo, el siguiente comando imprime todos los archivos con un '-'después de su nombre si son archivos normales, y de lo '+'contrario:

find / -type f -exec echo {} - ';' -o -exec echo {} + ';'

El cambio invalida el uso como este. Aunque el estándar anterior establecía que este uso funcionaría, en la práctica muchos no lo admitían y los desarrolladores del estándar consideraron que ahora era mejor decir que esto no era permisible.

PASC Interpretation 1003.2 # 210 entra en más detalles sobre la historia de -exec … {} +. Existía en varios sistemas Unix antes de que fuera adoptado por POSIX; el informe de defectos lo remonta a SVR4 (donde estaba en gran parte indocumentado). El informe de defectos justifica que el cambio incompatible tenga poco impacto en la práctica:

Tenga en cuenta que el "+" solo se trata como especial si inmediatamente sigue a "{}". Esto minimiza las posibilidades de causar problemas con los usos existentes de "+" como argumento con "-exec".

Aunque agregar soporte para -exec … {} +rompería algunas aplicaciones conformes, como el ejemplo anterior, hay menos de estas que si -exec … {} … +se permitieran.

Otra razón, tal vez, para restringir {}a ser el último argumento es la facilidad de implementación. Si {}se permitiera en cualquier lugar de la lista de argumentos -exec, el findprograma tendría que construir la línea de comando copiando los argumentos estáticos, luego la parte variable y luego otra parte estática. Esto dificultaría la construcción de la lista de argumentos y el límite de tamaño. La dificultad es mínima, pero a los implementadores les gusta cortar esquinas. Soportar múltiples instancias sustituibles de {}(si -exec {} foo +es para trabajar, lógicamente se puede esperar que eso -exec {} foo {} +también) sería significativamente más difícil.

Gilles 'SO- deja de ser malvado'
fuente