Perché c'è un / bin / echo e perché dovrei usarlo?


52

Ho notato che c'è un eseguibile binario /bin/echosul mio sistema Ubuntu MATE 17.04.

Ho pensato, è strano, perché

$ type echo
echo is a shell builtin

I test di cursori suggeriscono che /bin/echofa lo stesso tipo di cose che incorpora Bash echo:

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

Quindi, perché esiste un'altra versione di echoseparata dal programma Bash e perché o quando dovrei usarla?



2
@ bodhi.zazen È abbastanza utile anche se non è lo stesso, perché affronta il contrario di questa domanda. Questa domanda chiede perché echoviene fornita come shell incorporata, mentre questa chiede perché viene fornita come comando esterno.
Eliah Kagan,

3
Uno dei motivi è che non tutti usano bash. Immagino che / bin / echo sia precedente a bash, e gli sviluppatori hanno trovato utile / efficiente includerlo come integrato invece di usare l'eseguibile.
jamesqf,

Risposte:


87

Se si apre un bashprompt e si digita un echocomando, che utilizza una shell incorporata anziché in esecuzione /bin/echo. Le ragioni per cui è ancora importante /bin/echoesistere sono:

  1. Non stai sempre usando una shell. In una varietà di circostanze, si esegue un eseguibile direttamente e non attraverso una shell.
  2. Almeno in teoria, alcune shell non hanno un echobuiltin. Questo non è effettivamente richiesto.

Per espandere il # 1, si supponga di voler spostare tutti i file regolari i cui nomi iniziare con abcqualsiasi parte srca dest. Esistono diversi modi per farlo, ma uno di questi è:

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

Supponiamo, invece di eseguirlo, di vedere tutti i comandi che verranno eseguiti per primi. Bene, allora puoi anteporre echoal comando, proprio come potresti fare in altri contesti:

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

Ma findnon usa una shell. Funziona /bin/echo.

Inoltre findcon -execo-execdir , l' /bin/echoeseguibile verrà chiamato da altri programmi che eseguono essi stessi programmi ma non attraverso una shell. Ciò avviene con il xargscomando (che è legato a find), così come in molti altri contesti, come la Exec=linea di una .desktoplima . Un altro esempio è quando si esegue sudo echo, che può essere utile per verificare se sudofunziona.

Allo stesso modo, alcune shell hanno un printfbuiltin ma /usr/bin/printfesiste anche.

Un motivo meno comune possibile che potresti usare deliberatamente /bin/echoè se ti affidassi alle differenze tra esso e il echocomando fornito dalla tua shell. man echodocumenti /bin/echo; help echonei bash documenti l' bashintegrato. echonon è molto portabile, poiché implementazioni diverse, sia tra i sistemi operativi che tra le shell sullo stesso sistema operativo, supportano diverse opzioni (ad esempio, -e) e differiscono nel trattamento delle barre rovesciate . Naturalmente, è meglio evitare di fare affidamento su tali dettagli e utilizzare printfinvece, che è molto più portatile .

In bash, puoi anche typemostrare il builtin /bin/echo- supponendo che /binsia nel tuo $PATHcome dovrebbe sempre essere - passando la -abandiera :

$ type -a echo
echo is a shell builtin
echo is /bin/echo

21
E anche perché la specifica POSIX dice che deve essercene uno.
Glenn Jackman,

4
@glennjackman Speravo davvero che qualcuno potesse postare una risposta a riguardo, e spero che tu decida di farlo! C'è qualche sottigliezza coinvolta, tuttavia, poiché né Debian, Ubuntu, né GNU Coreutils (né il Progetto GNU in generale) cercano di conformarsi a POSIX in tutto . Ad esempio, POSIX insiste sul fatto che cdesiste un eseguibile (che, quando eseguito, cambia directory ed esce, lasciando il chiamante dove erano prima) e alcuni sistemi operativi ne hanno uno. Potrebbe essere utile citare 4.1 negli standard GNU .
Eliah Kagan,

@EliahKagan: Per inciso / usr / bin / cd ha un uso: il comando directory / usr / bin / cd esegue quel comando in quella directory. Se la modifica della directory non riesce, il comando non si avvia.
Giosuè,

4
@Joshua un uso migliore di cdè semplicemente come un test di capacità di accedere a una determinata directory: se ha /usr/bin/cd some/dirsuccesso, in un colpo hai testato: a) che some/diresiste, b) che è una directory o un collegamento a una, e c) il permessi necessari per accedere a quella directory esistono; tutto senza cambiare il tuo stato.
muru,

1
@CarlWitthoft, vedi Perché printf è meglio dell'eco? Inoltre non lo è /bin/echo, a \bin\echomeno che tu non stia utilizzando Windows. ;)
Wildcard il

31

Eliah ha fatto un ottimo lavoro nel rispondere a questa domanda, ma voglio commentare la parte "perché c'è un'altra versione di echoseparata dal programma Bash". Questa è la domanda sbagliata.

La domanda giusta è: perché in primo luogo si tratta di un comando incorporato , quando avrebbe potuto essere (ed è) un comando esterno perfettamente perfetto?

Per semplicità, dai un'occhiata al builtin in trattino, un misero 38 (bash ha 61, per confronto, andando dall'output di 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

Quanti di questi devono essere integrati? [, echo, false, printf, pwd, test, E truenon hanno bisogno di essere builtins: Non fanno nulla che solo un incorporato può fare (influenzare o ottenere lo stato di shell che non è disponibile a comandi esterni). printfAlmeno Bash si avvantaggia di essere un builtin: printf -v varsalva l'output nella variabile var. timein bash è anche speciale: essendo una parola chiave, puoi cronometrare elenchi di comandi arbitrari in bash (il trattino non ha un timeequivalente). pwdnon è nemmeno necessario che sia incorporato: qualsiasi comando esterno erediterà l'attuale directory di lavoro (ed è anche un comando esterno ).:è un'eccezione: è necessario un NOP ed :è così. Il resto fa azioni che un comando esterno può facilmente fare.

Quindi, un quinto di questi builtin non ha bisogno di essere builtin. Allora perche? La dashmanpage * spiega in realtà perché questi sono builtin (sottolineatura mia):

builtins
 Questa sezione elenca i comandi integrati che sono integrati perché
 è necessario eseguire alcune operazioni che non possono essere eseguite da un altro
 processi. Oltre a questi, ci sono molti altri comandi che possono
 essere integrato per efficienza (es. printf (1), echo (1), test (1), ecc.).

È praticamente tutto: questi builtin sono lì perché sono usati così spesso, interattivamente e negli script, e la loro funzionalità è abbastanza semplice, che la shell può fare il lavoro. E così accade: alcuni (?) La maggior parte delle conchiglie hanno preso sul lavoro ** Torna. Ilsh da 2.9 BSD , e non troverete un echoincorporato.

Quindi, è del tutto possibile che una shell minima possa saltare l'implementazione di comandi come builtin (non credo che ci sia nessuna shell corrente). Il progetto GNU coreutils non presuppone che tu li esegua in una particolare shell e POSIX richiede questi comandi. Quindi, coreutils fornisce questi comunque e salta quelli che non hanno alcun significato al di fuori della shell.


* Questo è quasi identico al corrispondente testo di manpage per la shell Almquist , su cui si basa il trattino, la shell Debian Almquist.

** zshporta questa idea all'estremo: i comandi che ricevi caricando vari moduli, come zmv, sono cose in cui non pensi che una shell debba nemmeno entrare . A quel punto, la vera domanda è: perché dovresti usare bash invece di zsh, che ha tutti questi builtin?


1
Si scopre che: non è nemmeno necessario che sia incorporato. È solo sciocco che non sia incorporato. A meno che tu non abbia a che fare con i primi problemi di init-floppy-disk a livello di init (nel qual caso ho scoperto che anche il pwd non funziona in modo affidabile) l'unica penalità per non averlo come incorporato è una prestazione terribile.
Giosuè,

5
@Joshua no, :dato che un esterno non sarebbe davvero un NOP, avresti comunque una PATHricerca, un tentativo di eseguire il comando, ecc., Quando tutto ciò che vuoi davvero è non fare espressamente nulla. :come incorporato lo fa.
muru,

2
Bash in realtà ha bisogno pwddi essere integrato per funzionare come fa, con il comportamento predefinito di mostrare il percorso "logico" ( pwd -L). /bin/pwdpotrebbe solo implementare il pwd -Pcomportamento di mostrarti le directory principali effettive, non il collegamento simbolico che hai cdpassato.
Peter Cordes,

2
Lo pwdstato di @PeterCordes è un po 'compromesso dalla presenza di PWD, ma sì, è anche un'istanza di bash che utilizza lo stato incorporato per migliorare la funzionalità
muru,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.