Pourquoi y a-t-il un / bin / echo et pourquoi voudrais-je l'utiliser?

52

J'ai remarqué qu'il y a un exécutable binaire /bin/echosur mon système Ubuntu MATE 17.04.

J'ai pensé, c'est étrange, parce que

$ type echo
echo is a shell builtin

Les tests Cursory suggèrent que cela /bin/echofait le même genre de chose que le Bash intégré echo:

$ /bin/echo foo
foo
$ /bin/echo $USER
zanna

Alors, pourquoi existe-t-il une autre version de echodistinct du programme Bash, et pourquoi ou quand voudrais-je l'utiliser?

Zanna
la source
2
@ bodhi.zazen C'est très utile même si ce n'est pas la même chose, car cela répond à l'inverse de cette question. Cette question demande pourquoi echoest fourni en tant que shell intégré, tandis que celui-ci demande pourquoi il est fourni en tant que commande externe.
Eliah Kagan
3
Une des raisons est que tout le monde n'utilise pas bash. Je suppose que / bin / echo a précédé bash et que les développeurs ont trouvé utile / efficace de l'inclure en tant que fonction intégrée au lieu d'utiliser l'exécutable.
jamesqf

Réponses:

87

Si vous ouvrez une bashinvite et tapez une echocommande, celle-ci utilise un shell intégré plutôt que l'exécution /bin/echo. Les raisons pour lesquelles il est toujours important /bin/echod'exister sont les suivantes:

  1. Vous n'utilisez pas toujours un shell. Dans diverses circonstances, vous exécutez un exécutable directement et non via un shell.
  2. Au moins en théorie, certains coquillages n’ont pas de fonction echointégrée. Ce n'est pas réellement nécessaire.

Pour développer # 1, supposons que vous vouliez déplacer tous les fichiers réguliers dont les noms commencé avec abcpartout dans srcla dest. Il y a plusieurs façons de le faire, mais l'une d'entre elles est:

find src -name 'abc*' -type f -exec mv -nv {} dest/ \;

Mais supposons plutôt que de simplement exécuter cela, vous voulez voir chaque commande qui sera exécutée en premier. Eh bien, alors vous pouvez ajouter echoune commande à la commande, comme dans d’autres contextes:

find src -name 'abc*' -type f -exec echo mv -nv {} dest/ \;

Mais findn'utilise pas de shell. Ça court /bin/echo.

Outre findavec -execou-execdir , l' /bin/echoexécutable sera appelé par d'autres programmes qui exécutent eux-mêmes des programmes, mais pas à l'aide d'un shell. Cela se produit avec la xargscommande (qui est liée à find), ainsi que dans un certain nombre d'autres contextes, tels que la Exec=ligne d' un .desktopfichier . Un autre exemple est le moment où vous exécutez sudo echo, ce qui peut être utile pour tester si sudofonctionne.

De même, certains coquillages ont un printfconstruit, mais /usr/bin/printfexiste également.

Une raison moins courante que vous pourriez utiliser délibérément /bin/echoest si vous vous en remettiez aux différences entre celui-ci et la echocommande fournie par votre shell. man echodocuments /bin/echo; help echodans les bash documents the bashbuiltin. echon’est pas très portable, car différentes implémentations - à la fois d’un système d’exploitation à l’autre et d’un même système d’exploitation - prennent en charge différentes options (par exemple, -e) et diffèrent dans le traitement des barres obliques inverses . Bien sûr, il vaut mieux éviter de s’appuyer sur de tels détails et utiliser à la printfplace, qui est beaucoup plus portable .

En bash, vous pouvez aussi faire le typeshow intégré /bin/echo- en supposant qu'il /binest dans votre $PATHcomme il se doit toujours - en lui passant le -adrapeau :

$ type -a echo
echo is a shell builtin
echo is /bin/echo
Eliah Kagan
la source
21
Et aussi parce que la spécification POSIX dit qu'il doit y en avoir un.
Glenn Jackman
4
@glennjackman J'espérais que quelqu'un posterait une réponse à ce sujet, en fait, et j'espère que vous déciderez de le faire! Cependant, aucune subtilité n'est en jeu, puisque ni Debian, Ubuntu, ni GNU Coreutils (ni le projet GNU dans son ensemble) n'essayent de se conformer à POSIX en tout . Par exemple, POSIX insiste sur le fait qu’il cdexiste un exécutable (qui, lorsqu’il est exécuté, change de répertoire et se ferme en laissant l’appelant là où il se trouvait auparavant) et que certains systèmes d’exploitation en ont un. Il peut être utile de citer 4.1 dans les normes GNU .
Eliah Kagan
@EliahKagan: Incidemment, / usr / bin / cd a une utilisation: / usr / bin / cd commande de répertoire exécute cette commande dans ce répertoire. Si le changement de répertoire échoue, la commande ne démarre pas.
Josué
4
@ Josué, une meilleure utilisation de cdest simplement un test de capacité à accéder à un répertoire donné: en cas de /usr/bin/cd some/dirsuccès, d'un coup, vous avez testé: a) qu'il some/direxiste, b) qu'il s'agit d'un répertoire ou d'un lien vers un, et c) le les autorisations requises pour que vous puissiez accéder à ce répertoire existent; tout cela sans changer votre propre état.
muru
1
@CarlWitthoft, voir Pourquoi printf est-il meilleur que l'écho? En outre, c’est /bin/echonon \bin\echo, sauf si vous utilisez Windows. ;)
Wildcard
31

Eliah a très bien répondu à cette question, mais je tiens à commenter la partie "pourquoi existe-t-il une autre version de" echodistinct du programme Bash "? C'est la mauvaise question.

La bonne question est: pourquoi est-ce un processus intégré en premier lieu , alors que cela aurait pu être (et est) une commande externe parfaitement fine?

Pour plus de simplicité, jetez un coup d’œil aux commandes intégrées dans dash, un maigre 38 (bash en a 61, à titre de comparaison, en se basant sur le résultat de compgen -b):

.               continue        getopts         readonly        type
:               echo            hash            return          ulimit
[               eval            jobs            set             umask
alias           exec            kill            shift           unalias
bg              exit            local           test            unset
break           export          printf          times           wait
cd              false           pwd             trap
command         fg              read            true

Combien d'entre eux doivent être intégrés? [, echo, false, printf, pwd, testEt truene doivent être builtins: Ils ne font rien que seul un builtin peut faire (affecter ou obtenir l' état shell qui n'est pas disponible aux commandes externes). Bash's printfprofite au moins d'être intégré: printf -v varenregistre le résultat dans la variable var. timein bash est également spécial: en étant un mot clé, vous pouvez chronométrer des listes de commandes arbitraires en bash (dash n’a pas d’ timeéquivalent). pwdne doit pas non plus être intégré - toute commande externe héritera du répertoire de travail actuel (et il s'agit également d'une commande externe ).:est une exception - vous avez besoin d'un NOP, et :c'est tout. Les autres font des actions qu'une commande externe peut facilement faire.

Ainsi, un cinquième de ces tâches intégrées n'a pas besoin d'être intégré. Pourquoi alors? La dashpage de manuel * explique en passant pourquoi elles sont intégrées (emphase moi):

Builtins
 Cette section répertorie les commandes intégrées qui sont intégrées car elles
 besoin d'effectuer une opération qui ne peut pas être effectuée par un séparé
 processus. En plus de cela, plusieurs autres commandes peuvent être utilisées.
 être intégré pour plus d'efficacité (par exemple, printf (1), echo (1), test (1), etc.).

C'est à peu près tout: ces fonctions intégrées existent, car elles sont utilisées très souvent, de manière interactive et dans des scripts, et leur fonctionnalité est suffisamment simple pour que le shell puisse faire le travail. Et il arrive: certains (?) La plupart des obus ont au travail ** Retour à. Lash de 2.9 BSD , et vous ne trouverez pas un echobuiltin.

Donc, il est tout à fait possible qu'un shell minimal puisse ignorer l'implémentation de telles commandes en tant que commandes intégrées (je ne pense pas que tout shell actuel le fasse). Le projet GNU coreutils ne suppose pas que vous allez les exécuter dans un shell particulier, et POSIX requiert ces commandes. Donc, coreutils les fournit quand même, et saute ceux qui n’ont aucune signification en dehors de la coquille.


* Ceci est presque identique au texte de la page de manuel correspondant au shell Almquist , sur lequel est basé dash, le shell Debian Almquist.

** zshpousse cette idée à l'extrême: les commandes que vous obtenez en chargeant différents modules, par exemple zmv, sont des choses que vous ne penseriez même pas qu'un shell devrait avoir . A ce stade, la vraie question est: pourquoi voudriez-vous utiliser bash au lieu de zsh, qui a toutes ces fonctions intégrées?

muru
la source
1
Il s'avère que: ne doit pas non plus être intégré. C'est juste idiot que ça ne soit pas un construit. Sauf si vous avez à faire face à des problèmes initiaux au niveau de la disquette de sauvetage (dans ce cas, j’ai découvert que pwd ne fonctionne pas de manière fiable non plus), la seule pénalité pour ne pas avoir cela en tant que fonction intégrée est une performance épouvantable.
Joshua
5
@ Josué non, :car un externe ne serait pas vraiment un NOP, vous auriez PATHquand même une recherche, une tentative d'exécution de la commande, etc., alors que tout ce que vous voulez vraiment est de ne rien faire expressément. :comme intégré fait cela.
Muru
2
Bash doit en fait pwdêtre intégré pour fonctionner correctement, avec le comportement par défaut consistant à afficher le chemin "logique" ( pwd -L). /bin/pwdpourrait seulement implémenter le pwd -Pcomportement de vous montrer les répertoires parents réels, pas le lien symbolique cdpar lequel vous avez traversé.
Peter Cordes
2
pwdLe statut de @PeterCordes est un peu compromis par la présence de PWD, mais oui, c'est aussi une instance de bash qui utilise le statut intégré pour améliorer la fonctionnalité
muru