GNU trouve et masque le {} pour certains obus – qui?

La page de manuel de GNU trouve des états:

-exec command ; [...] The ssortingng `{}' is replaced by the current file name being processed everywhere it occurs in the arguments to the command, not just in arguments where it is alone, as in some versions of find. Both of these constructions might need to be escaped (with a `\') or quoted to protect them from expansion by the shell. 

C'est de l'homme à find (GNU findutils) 4.4.2.

Maintenant, j'ai testé ceci avec bash et tiret, et les deux n'ont pas besoin d'avoir le {} être masqué. Voici un test simple:

 find /etc -name "hosts" -exec md5sum {} \; 

Y a-t-il une coquille, pour laquelle j'ai vraiment besoin de masquer les bretelles? Notez que cela ne dépend pas du fait que le file trouvé contient un blanc (invoqué depuis bash):

 find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \; /home/stefan/Ubuntu One 

Cela change si le file trouvé est passé à un sous-shell:

 find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d {}' \; ls: cannot access /home/stefan/Ubuntu: No such file or directory ls: cannot access One: No such file or directory 

qui peut être résolu par:

 find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "$0"' {} \; 

contrairement à:

 find ~ -maxdepth 3 -type d -name "U*" -exec bash -c 'ls -d "{}"' \; /home/stefan/Ubuntu One 

mais ce n'est pas ce dont parle la page man, n'est-ce pas? Alors quelle coquille traite {} d'une manière différente?

    Résumé : S'il y a déjà eu un shell qui a été développé {} , c'est vraiment du vieux truc.

    Dans la coquille de Bourne et dans les coquilles POSIX, les accolades ( { et } ) sont des caractères ordinaires (contrairement à ( et ) qui sont des délimiteurs de mots comme ; et & , et [ et ] qui sont des caractères globuleux). Les strings suivantes sont toutes censées être imprimées littéralement:

     $ echo { } {} {foo,bar} {1..3} { } {} {foo,bar} {1..3} 

    Un mot composé d'une seule accolade est un mot réservé , qui n'est spécial que s'il s'agit du premier mot d'une command.

    Ksh implémente l'extension de l'accolade comme une extension incompatible avec la shell Bourne. Cela peut être désactivé avec set +B Bash émule ksh à cet égard. Zsh implémente aussi l'expansion de l'accolade; il peut être désactivé avec set +I ou setopt ignore_braces ou emulate sh . Aucun de ces shells ne développe {} dans tous les cas, même quand c'est une sous-string d'un mot (par exemple foo{}bar ), en raison de l'utilisation courante dans les arguments à find et xargs .

    Single Unix v2 note que

    Dans certains systèmes historiques, les accolades sont traitées comme des opérateurs de contrôle. Pour faciliter les futures activités de normalisation, les applications portables devraient éviter d'utiliser des accolades non représentées pour représenter les caractères eux-mêmes. Il est possible qu'une version future de la norme ISO / CEI 9945-2: 1993 puisse exiger que { et } soient traités individuellement comme opérateurs de contrôle, bien que le jeton {} soit probablement une exception -utilisé find {} construct.

    Cette note a été supprimée dans les versions ultérieures de la norme; les exemples de find ont des utilisations non-guillemets de {} , comme les exemples pour xargs . Il y a peut-être eu des coquilles de Bourne historiques où {} a dû être cité, mais ce serait vraiment de vieux systèmes existants.

    Les implémentations csh que j'ai sous la main (OpenBSD 4.7, BSD csh sur Debian , tcsh) développent toutes {foo} pour foo mais ne laissent que {} .

    Le {} doit être cité dans la coquille de fish .

     $ fish -c 'echo find -exec {} \;' find -exec ; 

    Et dans la coquille rc (également akanga basé sur rc , mais pas es ):

     $ rc -c "echo find -exec {} ';'" line 1: syntax error near '{' 

    Ce ne sont probablement pas les coquilles que les auteurs de cette documentation GNU avaient en tête quand ils ont écrit ce text depuis fish sortie du fish en 2005 (alors que ce text existait déjà en 1994) et que rc n'était pas à l'origine un shell Unix.

    Il y a des rumeurs de certaines versions de csh (le shell qui a introduit l'expansion de l'accolade) l'exigeant. Mais il est difficile de donner crédit à ceux depuis la première version de csh dans 2BSD n'a pas. Ici testé dans un émulateur PDP11:

     # echo find -exec {} \; find -exec {} ; 

    Et la page de manuel de 2BSD csh indique clairement :

    Dans le cas particulier `{',`}' et `{} 'sont passés sans perturbation.

    Donc, je findais très étrange si une version ultérieure de csh ou tcsh a cassé plus tard.

    Cela aurait pu être de contourner quelques bugs dans certaines versions. Toujours avec cette 2BSD csh (c'est la même chose dans 2.79BSD, 2.8BSD, 2.11BSD):

     # csh -x # echo foo {} bar echo foo {} bar foo {} bar # echo `echo foo {} bar` echo `echo foo {} bar` echo foo {} bar foo bar 

    Citant n'aide pas cependant:

     # echo `echo foo '{}' bar` echo `echo foo '{}' bar` echo foo {} bar foo bar 

    Vous pourriez citer la substitution complète de la command:

     # echo "`echo foo {} bar`" echo `echo foo {} bar` echo foo {} bar foo {} bar 

    Mais c'est en passant un argument à cet écho externe.

    Dans csh ou tcsh , vous devriez citer le {} quand il ne l'est pas tout seul comme dans:

     find . -name '*.txt' -type f -exec cp {} '{}.back' \; 

    (bien que ce type d'utilisation de la find ne soit pas portable car certains ne développent que {} quand ils sont seuls).

    En un mot, csh . bash et d'autres coquilles modernes reconnaissent que l'user ne request probablement pas une extension d'accolade nulle. ( csh moderne est en fait tcsh et peut également gérer {} sanely maintenant.)