Utilisation d'accolades fermantes {} comme arguments des commandes et de leurs options

11

Exemples

J'ai récemment trouvé des exemples d'utilisation de paires d'accolades englobantes {}, sans rien entre les accolades ouvrantes et fermantes, comme arguments des commandes et même de leurs options:

cat foo | xargs -I{} echo {}

find . -size 0 -exec rm -i {} \;

Pas de documentation

Mon problème est que je ne trouve pas de documentation dans le manuel GNU Bash qui décrit l'utilisation de {}dans un tel contexte comme dans les exemples ci-dessus.

Je ne pense pas que ce soit une expansion de paramètre , car un signe dollar doit précéder les accolades englobantes dans une expansion de paramètre comme dans ${}.

Ce ne peut pas non plus être une extension d'accolade , car elle prend la forme de {x..y[..incr]}, où xet ynon facultative.

Il ne peut pas non plus s'agir d'un groupe de commandes , car il {}est utilisé comme arguments.

Des questions

  1. Qu'est-ce qu'une paire d'accolades englobantes {}signifie même, en général, comme argument pour toute commande qui l'accepte?

  2. Où puis-je trouver une documentation décrivant l'utilisation de {}as comme arguments?

Niko Gambt
la source
Certaines commandes ont ces options {}- ce targetsqui signifie agir sur, avec la findcommande, ce sont les rmfichiers supprimés / trouvés.
Tuyen Pham

Réponses:

16

Ces accolades bouclées sont laissées seules par bash; ils appartiennent findet xargs, respectivement, et sont décrits dans leur man-pages.

man find

-exec commander ;

Exécuter la commande ; true si l'état 0 est renvoyé. Tous les arguments suivants à rechercher sont considérés comme des arguments de la commande jusqu'à ce qu'un argument composé de ;soit rencontré. La chaîne {}est remplacée par le nom du fichier en cours de traitement partout où il apparaît dans les arguments de la commande, pas seulement dans les arguments où il est seul, comme dans certaines versions de find. Il peut être nécessaire d'échapper à ces deux constructions (avec un \) ou de les citer pour les protéger de l'expansion par le shell. Voir la section EXEMPLES pour des exemples d'utilisation de l' -execoption. La commande spécifiée est exécuté une fois pour chaque fichier correspondant. La commande est exécutée dans le répertoire de départ. Il existe des problèmes de sécurité inévitables entourant l'utilisation de l' -exec action; vous devez utiliser l' -execdiroption à la place.

-exec commander {} +

Cette variante de l' -execaction exécute la commande spécifiée sur les fichiers sélectionnés, mais la ligne de commande est créée en ajoutant à la fin chaque nom de fichier sélectionné; le nombre total d'appels de la commande sera bien inférieur au nombre de fichiers correspondants. La ligne de commande est construite à peu près de la même manière que xargsses lignes de commande. Une seule instance de {}est autorisée dans la commande. La commande est exécutée dans le répertoire de départ. Si findrencontre une erreur, cela peut parfois provoquer une sortie immédiate, donc certaines commandes en attente peuvent ne pas être exécutées du tout. Cette variante de -execrenvoie toujours vrai.

-execdir commander ;

-execdir commander {} +

Comme -exec, mais la commande spécifiée est exécutée à partir du sous-répertoire contenant le fichier correspondant, qui n'est normalement pas le répertoire dans lequel vous avez commencé la recherche. Il s'agit d'une méthode beaucoup plus sécurisée pour appeler des commandes, car elle évite les conditions de concurrence lors de la résolution des chemins d'accès aux fichiers correspondants. Comme pour l' -exec action, le + formulaire de -execdir va construire une ligne de commande pour traiter plus d'un fichier correspondant, mais toute invocation de commande donnée ne listera que les fichiers qui existent dans le même sous-répertoire. Si vous utilisez cette option, vous devez vous assurer que votre $PATHvariable d'environnement ne fait pas référence.; sinon, un attaquant peut exécuter n'importe quelle commande qu'il souhaite en laissant un fichier correctement nommé dans un répertoire dans lequel vous l'exécuterez -execdir. Il en va de même pour les entrées $PATHqui sont vides ou qui ne sont pas des noms de répertoire absolus. Si findrencontre une erreur, cela peut parfois provoquer une sortie immédiate, donc certaines commandes en attente peuvent ne pas être exécutées du tout. Le résultat de l'action dépend de l'utilisation de la +ou de la ;variante; -execdir la commande {} + retourne toujours vrai, tandis que la -execdir commande ne {} ; retourne vrai que si la commande retourne 0.

man xargs

-I replace-str

Remplacez les occurrences de replace-str dans les arguments initiaux par des noms lus à partir de l'entrée standard. De plus, les blancs non entre guillemets ne terminent pas les éléments d'entrée; au lieu de cela, le séparateur est le caractère de nouvelle ligne. Implique -xet -L 1.

-i[ replace-str ], --replace[ =replace-str ]

Cette option est synonyme de -Ireplace-str si replace-str est spécifié. Si l' argument replace-str est manquant, l'effet est le même que -I{}. Cette option est déconseillée; utiliser à la -Iplace.

Edit: et ici POURQUOI bash ignore ces accolades:

man bash

{ liste; }

La liste est simplement exécutée dans l'environnement shell actuel. la liste doit se terminer par une nouvelle ligne ou un point-virgule. C'est ce qu'on appelle une commande de groupe. Le statut de retour est le statut de sortie de la liste. Notez que contrairement aux métacaractères ( et ) , { et } sont des mots réservés et doivent se produire lorsqu'un mot réservé est autorisé à être reconnu. Comme ils ne provoquent pas de rupture de mot, ils doivent être séparés de la liste par des espaces ou un autre métacaractère shell.

Pour mettre l'accent: la liste doit se terminer par une nouvelle ligne ou un point-virgule .

tink
la source
1
Je vous remercie! Je suis ennuyé que celui qui a écrit man xargsn'ait même pas pris la peine d'expliquer ce que cela {}signifie réellement, ni que l'auteur ait redirigé (sans jeu de mots) le lecteur vers l'explication de -execdans la page de manuel de find.
Niko Gambt le
@NikoGambt - Je sympathise ...
tink
5
@NikoGambt Eh bien, {} ne signifie vraiment rien pour xargs, sauf qu'il s'agit de la valeur par défaut pour -i, qui est obsolète. Je ne sais pas quelle explication est nécessaire au-delà de cela. Dans l'exemple que vous avez publié, il aurait tout aussi bien pu l'être xargs -Iab echo ab; c'est un choix purement arbitraire.
Random832
@ Random832 Après avoir fait plus de tests avec -I, je comprends maintenant ce que fait réellement cette option. Oui, {}c'est arbitraire, comme vous l'avez dit. J'étais juste confus par l'explication If the replace-str argument is missing, the effect is the same as -I{}. Si -Isans argument était le même que -I{}, alors cat foo | xargs -I echo {}produirait le même résultat que l'exécution cat foo | xargs -I{} echo {}. Mais ce ne sont pas les mêmes. Le premier est une erreur, et ce qui m'a encore plus dérouté, c'est le message d'erreur xargs: {}: No such file or directory, mais c'est simplement dû à la mise en œuvre.
Niko Gambt le
1
@NikoGambt -I(majuscule I) ne peut pas être exécuté sans argument. L'argument -Iétait echo. Il s'agit de la principale différence entre -Iet -i(et la raison pour laquelle -i est déconseillée, car les options avec des arguments non requis sont rares et déroutantes)
Random832