Pourquoi «find -exec cmd {} +» doit-il se terminer par «{} +»?

11

Préface: Je comprends la différence entre -exec {} \;& -exec {} +. Je n'ai pas non plus de problème en tant que tel , je suis juste curieux de connaître la sémantique de find.


Lorsque vous terminez l' -execargument avec +au lieu de ;, nous devons terminer cela avec {} +, par exemple:

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

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

L'utilisation ;dans ces exemples au lieu de +fonctionne très bien (mais fait évidemment autre chose).

De POSIX :

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

... Seul un <plus-sign> qui suit immédiatement un argument ne contenant que les deux caractères " {}" doit ponctuer la fin de l'expression principale. Les autres utilisations de <plus-sign> ne doivent pas être traitées comme spéciales.

En d'autres termes, lorsque vous utilisez le +, la commande doit se terminer par {} +.

Pourquoi est-ce? Et pourquoi seulement avec le +et non le ;? Au début, je pensais peut-être éviter les conflits avec les noms de fichiers qui contiennent un +, mais les noms de fichiers avec un ;semblent bien fonctionner? J'ai du mal à croire que cette limitation est arbitraire ...

Martin Tournoij
la source
3
FWIW, la page POSIX indique également que The "-exec ... {} +" syntax adopted was a result of IEEE PASC Interpretation 1003.2 #210et dans ce document, vous trouverez plus de détails, par exemple: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

Réponses:

5

La justification donnée dans la spécification POSIX est:

La "-exec ... {} +"syntaxe adoptée est le résultat de l'interprétation IEEE PASC 1003.2 # 210. Il convient de noter qu'il s'agit d'un changement incompatible avec la norme ISO / IEC 9899: 1999. Par exemple, la commande suivante imprime tous les fichiers avec un '-'après leur nom s'il s'agit de fichiers normaux et '+'sinon:

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

La modification invalide une telle utilisation. Même si la norme précédente indiquait que cette utilisation fonctionnerait, dans la pratique, beaucoup ne la prenaient pas en charge et les développeurs de normes jugeaient préférable de déclarer maintenant que cela n'était pas autorisé.

L'interprétation PASC 1003.2 # 210 donne plus de détails sur l'histoire de -exec … {} +. Il existait sur plusieurs systèmes Unix avant d'être adopté par POSIX; le rapport d'anomalie le retrace à SVR4 (où il était largement non documenté). Le rapport d'anomalie justifie le changement incompatible comme ayant peu d'impact dans la pratique:

Notez que le "+" n'est traité comme spécial que s'il suit immédiatement "{}". Cela minimise les chances de provoquer des problèmes avec les utilisations existantes de "+" comme argument avec "-exec".

Bien que l'ajout de la prise en charge de -exec … {} +briserait certaines applications conformes telles que l'exemple ci-dessus, il y en a moins que si cela -exec … {} … +était autorisé.

Une autre raison, peut-être, de limiter {}le dernier argument est la facilité de mise en œuvre. S'il {}était autorisé n'importe où dans la liste des arguments -exec, le findprogramme devrait créer la ligne de commande en copiant les arguments statiques, puis la partie variable, puis une autre partie statique. Cela rendrait plus difficile la construction de la liste des arguments et la prise en compte de la taille limite. La difficulté est minime, mais les réalisateurs aiment couper les coins ronds. La prise en charge de plusieurs instances substituables de {}(si cela -exec {} foo +doit fonctionner, on peut logiquement s'attendre à ce -exec {} foo {} +qu'il en soit de même) serait considérablement plus difficile.

Gilles 'SO- arrête d'être méchant'
la source