La page de manuel de GNU Find indique les états suivants:
-exec command ; [...] The string `{}' 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.
Cela va de l'homme à find
(GNU findutils) 4.4.2.
Maintenant, j'ai testé cela avec bash et dash, et les deux n'ont pas besoin d' {}
être masqués. Voici un test simple:
find /etc -name "hosts" -exec md5sum {} \;
Y at-il une coquille, pour laquelle j'ai vraiment besoin de masquer les accolades? Notez que cela ne dépend pas de savoir si le fichier trouvé contient un blanc (appelé depuis bash):
find ~ -maxdepth 1 -type d -name "U*" -exec ls -d {} \;
/home/stefan/Ubuntu One
Cela change si le fichier trouvé est passé dans 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 de manuel, n'est-ce pas? Alors, quelle coquille traite {}
d'une manière différente?
Réponses:
Résumé : Si jamais un shell s’agrandissait
{}
, c’est maintenant du passé .Dans le shell Bourne et dans les shell compatibles 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 globaux). Les chaînes suivantes sont toutes supposées être imprimées littéralement:Un mot constitué d'une seule accolade est un mot réservé , qui n'est spécial que s'il s'agit du premier mot d'une commande.
Ksh implémente le développement d'accolade en tant qu'extension incompatible du shell Bourne. Cela peut être désactivé avec
set +B
. Bash émule ksh à cet égard. Zsh implémente également l'expansion des corsets; il peut être désactivé avecset +I
ousetopt ignore_braces
ouemulate sh
.{}
En aucun cas, aucun de ces shells ne se développe , même s'il s'agit d'une sous-chaîne d'un mot (par exemplefoo{}bar
), en raison de l'utilisation courante dans les arguments defind
etxargs
.Single Unix v2 note que
Cette note a été supprimée dans les versions suivantes de la norme. les exemples pour
find
des utilisations non citées de{}
, de même que les exemples pourxargs
. Il y a peut-être eu des coquilles Bourne historiques où il a{}
fallu citer, mais il s'agirait vraiment de vieux systèmes hérités.Les implémentations csh que j'ai sous la main (OpenBSD 4.7, BSD csh sur Debian , tcsh) se développent toutes
{foo}
enfoo
laissant de côté{}
.la source
bash
(voir$BASH_VERSION
). L’expansion du corset est très bien vivante.{}
syntaxe est originaire decsh
, mais{}
étendue à la chaîne vide. Les nouveaux obus reconnaissent que c'est absurde, mais il y a encore du vieuxcsh
.{}foo
s'étendrait àfoo
, mais étendrait{}
à{}
(sauf quand dans les backticks, mais citer ne aiderait pas) et a été documenté en tant que tel. Je l'ai vérifié pour le csh de 2BSD (première version), 2.79BSD, 2.8BSD et 2.11BSD.Le
{}
besoin d'être cité dans les versions dufish
shell avant la version 3.0.0.Et dans le shell rc (également
akanga
basé surrc
, mais pases
):Ce ne sont probablement pas les réservoirs que les auteurs de la documentation de découverte GNU avaient en tête lorsqu'ils ont écrit ce texte depuis
fish
sa première publication en 2005 (alors que ce texte ou similaire existait déjà en 1994) et qu'ilrc
ne s'agissait pas à l'origine d'un shell Unix.Certaines rumeurs disent que certaines versions de
csh
(le shell qui a introduit le développement par accolade) en ont besoin. Mais il est difficile d’en attribuer le mérite à ceux qui se sont produits depuis la première version decsh
2BSD. Ici comme testé dans un émulateur PDP11:Et la page de manuel de 2BSD
csh
indique clairement :Donc, je trouverais cela très étrange si une version ultérieure de csh ou de tcsh le cassait plus tard.
Cela aurait pu être de contourner certains bugs dans certaines versions. Toujours avec ce csh 2BSD (c'est la même chose dans 2.79BSD, 2.8BSD, 2.11BSD):
Citant n'aide pas si:
Vous pouvez citer toute la substitution de commande:
Mais cela passe un argument à cet écho extérieur.
En
csh
outcsh
, vous auriez besoin de citer le{}
quand pas seul comme dans:(Bien que ce type d’
find
utilisation ne soit pas portable car certainsfind
ne s’agrandissent{}
que par eux-mêmes).la source
En un mot,
csh
.bash
et d'autres coques modernes reconnaissent que l'utilisateur ne demande probablement pas une extension null Brace. (Modernecsh
est en faittcsh
et peut également traiter de manière{}
saine maintenant.)la source
csh
. Tout le monde n’exécute pas les utilitaires GNU sous Linux; en fait, il est assez courant de les installer sur des systèmes Unix commerciaux plus anciens dont les commandes groupées sont limitées. (Le remplacementcsh
sur ces systèmes est moins probable, car les scripts système peuvent s'appuyer sur les particularités de l'originalcsh
, et même si les utilisateurs étaient tous configurés pour utiliser une nouvelle versioncsh
, ilroot
faudrait presque certainement conserver la versionpdksh
la bonne chose à faire… bien que la bonne réponse à cette question est probablement «le réelksh
est le logiciel libre, ces temps-ci»...
pour ksh93, bash et zsh). Only (t) csh se développe{foo}
enfoo
, et même il reste{}
seul (au moins sur les BSD récents).