¿Por qué hay un / bin / echo y por qué querría usarlo?

Noté que hay un ejecutable binario /bin/echo en mi sistema Ubuntu MATE 17.04.

Pensé, eso es extraño, porque

 $ type echo echo is a shell builtin 

Las pruebas cursivas sugieren que /bin/echo hace lo mismo que el echo incorporado de Bash:

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

Entonces, ¿por qué hay otra versión de echo separada del progtwig Bash, y por qué o cuándo querría usarla?

Si abres un indicador de bash y escribes un comando echo , utiliza un shell incorporado en lugar de ejecutar /bin/echo . Las razones por las que todavía es importante que exista /bin/echo son:

  1. No siempre estás usando una concha. En diversas circunstancias, ejecuta un ejecutable directamente y no a través de un shell.
  2. Al menos en teoría, algunas conchas no tienen un echo incorporado. Esto no es realmente requerido

Para expandir el # 1, suponga que desea mover todos los archivos regulares cuyos nombres comenzaron con abc cualquier lugar en src a dest . Hay varias formas de hacerlo, pero una de ellas es:

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

Pero suponga que, en lugar de simplemente ejecutar eso, quiere ver cada comando que se ejecutará primero. Bueno, entonces puedes añadir echo al comando, tal como lo harías en otros contextos:

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

Pero el find no usa una concha. Eso corre /bin/echo .

Además de find con -exec o -execdir , el ejecutable /bin/echo será llamado por otros progtwigs que ejecutan progtwigs, pero no a través de un shell. Esto sucede con el comando xargs (que está relacionado con la find ), así como en varios otros contextos, como la línea Exec= de un archivo .desktop . Otro ejemplo es cuando ejecuta sudo echo , que puede ser útil para probar si sudo está funcionando.

De manera similar, algunos shells tienen un printf incorporado pero /usr/bin/printf también existe.

Una posible razón menos común por la que podría usar deliberadamente /bin/echo es si confiara en las diferencias entre éste y el comando echo provisto por su shell. man echo documents /bin/echo ; help echo en documentos bash el bash builtin. echo no es muy portátil, porque las diferentes implementaciones, tanto en los sistemas operativos como en los distintos shells en el mismo sistema operativo, admiten diferentes opciones (por ejemplo, -e ) y difieren en el tratamiento de las barras invertidas . Por supuesto, es mejor evitar confiar en tales detalles y utilizar printf , que es mucho más portátil .

En bash , también puede hacer que el type incorporado show /bin/echo – asumiendo que /bin esté en su $PATH como debería ser siempre – pasándole la bandera -a :

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

Eliah ha hecho un gran trabajo al responder esto, pero quiero comentar sobre la parte de “por qué hay otra versión de echo separada del progtwig Bash”. Esa es la pregunta equivocada.

La pregunta correcta es: ¿por qué es esto una función incorporada en primer lugar , cuando podría haber sido (y es) un comando externo perfectamente correcto?

Para simplificar, eche un vistazo a las incorporaciones en el tablero, un miserable 38 (bash tiene 61, para comparación, yendo por la salida 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 

¿Cuántos de estos necesitan ser construidos? [ , echo , false , printf , pwd , test , y true no necesitan ser incorporados: no hacen nada que solo puede hacer un incorporado (afecta u obtiene un estado de shell que no está disponible para comandos externos). Printf de Bash, al menos, se aprovecha de ser incorporado: printf -v var guarda la salida en la variable var . time en bash también es especial: al ser una palabra clave, puede cronometrar listas de comandos arbitrarias en bash (el guión no tiene un time equivalente). pwd tampoco necesita ser un componente interno, cualquier comando externo heredará el directorio de trabajo actual (y también es un comando externo ). : es una excepción – necesitas un NOP, y : es eso. El rest realiza acciones que un comando externo puede hacer fácilmente.

Por lo tanto, una quinta parte de estas incorporaciones no necesitan ser integradas. ¿Porqué entonces? La página de manual del dash * en realidad explica por qué estos están integrados (énfasis mío):

  Builtins
  Esta sección enumera los comandos incorporados que están incorporados porque
  Necesito realizar alguna operación que no pueda ser realizada por separado
  proceso.  Además de estos, hay varios otros comandos que pueden 
   estar integrado en la eficiencia (por ejemplo, printf (1), eco (1), prueba (1), etc.). 

Eso es todo: estos elementos incorporados están allí porque se usan con mucha frecuencia, de forma interactiva y en scripts, y su funcionalidad es lo suficientemente simple, que el shell puede hacer el trabajo. Y así sucede: algunos shells (¿la mayoría?) Tomaron el trabajo. ** Vuelva a la sh de 2.9 BSD , y no encontrará echo incorporado.

Por lo tanto, es completamente posible que un shell mínimo pueda omitir la implementación de comandos como builtins (aunque no creo que ningún shell actual lo haga). El proyecto coreutils de GNU no asume que los vas a ejecutar en un shell en particular, y POSIX requiere estos comandos. Por lo tanto, coreutils proporciona estos de todos modos, y omite aquellos que no tienen ningún significado fuera de la shell.


* Esto es casi idéntico al texto de la página de manual correspondiente para el shell de Almquist , que es en lo que se basa el dash, el shell de Debian Almquist.

** zsh lleva esta idea al extremo: los comandos que se obtienen al cargar varios módulos, como zmv , son cosas que no zmv que necesitara una shell . En ese punto, la verdadera pregunta es: ¿por qué usarías bash en lugar de zsh, que tiene todos estos elementos integrados?