Diferencia entre sh y bash
Cuando escribimos programas de shell, a menudo usamos /bin/sh
y /bin/bash
. Normalmente uso bash
, pero no sé cuál es la diferencia entre ellos.
¿Cuál es la principal diferencia entre Bash y sh
?
¿Qué debemos tener en cuenta al programar en Bash y sh
?
¿Qué es la mierda?
sh
(o Shell Command Language) es un lenguaje de programación descrito por el estándar POSIX . Tiene muchas implementaciones ( ksh88
, Dash , ...). Bash también puede considerarse una implementación de sh
(ver más abajo).
Porque sh
es una especificación, no una implementación, /bin/sh
es un enlace simbólico (o un enlace físico) a una implementación real en la mayoría de los sistemas POSIX.
¿Qué es Bash?
Bash comenzó como una sh
implementación compatible (aunque es anterior al estándar POSIX por algunos años), pero con el paso del tiempo ha adquirido muchas extensiones. Muchas de estas extensiones pueden cambiar el comportamiento de los scripts de shell POSIX válidos, por lo que Bash por sí solo no es un shell POSIX válido. Más bien, es un dialecto del lenguaje shell POSIX.
Bash admite un --posix
conmutador, lo que lo hace más compatible con POSIX. También intenta imitar POSIX si se invoca como sh
.
sh = golpe?
Durante mucho tiempo, /bin/sh
solía señalar /bin/bash
en la mayoría de los sistemas GNU/Linux. Como resultado, casi era seguro ignorar la diferencia entre los dos. Pero eso empezó a cambiar recientemente.
Algunos ejemplos populares de sistemas /bin/sh
a los que no apunta /bin/bash
(y algunos de los cuales /bin/bash
pueden ni siquiera existir) son:
- Sistemas modernos Debian y Ubuntu, con enlaces simbólicos
sh
dedash
forma predeterminada; - Busybox , que normalmente se ejecuta durante el tiempo de arranque del sistema Linux como parte de
initramfs
. Utiliza la implementación de shell ash . - Sistemas BSD y, en general, cualquier sistema que no sea Linux. Utiliza OpenBSD
pdksh
, un descendiente de KornShell . FreeBSDsh
es un descendiente del shell Bourne de Unix original. Solaris tiene el suyo propiosh
que durante mucho tiempo no fue compatible con POSIX; Hay una implementación gratuita disponible en el proyecto Heirloom .
¿ Cómo puede saber qué /bin/sh
puntos hay en su sistema?
La complicación es que /bin/sh
podría ser un vínculo simbólico o un vínculo físico. Si es un enlace simbólico, una forma portátil de resolverlo es:
% file -h /bin/sh
/bin/sh: symbolic link to bash
Si es un enlace físico, prueba
% find -L /bin -samefile /bin/sh
/bin/sh
/bin/bash
De hecho, la -L
bandera cubre tanto enlaces simbólicos como enlaces duros, pero la desventaja de este método es que no es portátil: POSIX no requiere find
admitir la -samefile
opción, aunque tanto GNU find como FreeBSD find la admiten.
línea shebang
En última instancia, depende de usted decidir cuál usar, escribiendo la línea «shebang» como la primera línea del guión.
P.ej
#!/bin/sh
usará sh
(y lo que sea que eso indique),
#!/bin/bash
se utilizará /bin/bash
si está disponible (y fallará con un mensaje de error si no lo está). Por supuesto, también puede especificar otra implementación, por ejemplo
#!/bin/dash
cual usar
Para mis propios scripts, los prefiero sh
por las siguientes razones:
- esta estandarizado
- es mucho más simple y fácil de aprender
- es portátil a través de sistemas POSIX; incluso si no lo tienen
bash
, deben tenerlosh
bash
El uso también tiene ventajas . Sus características hacen que la programación sea más conveniente y similar a la programación en otros lenguajes de programación modernos. Estos incluyen cosas como matrices y variables locales con alcance. Plain sh
es un lenguaje de programación muy minimalista.
sh
: http://man.cx/sh
Bash: http://man.cx/bash
TL;DR : Bash es un superconjunto sh
con una sintaxis más elegante y más funcionalidad. Es seguro utilizar una línea Bash shebang en casi todos los casos, ya que es bastante omnipresente en las plataformas modernas.
NB: en algunos entornos, sh
es Bash. Controlar sh --version
.
Esta pregunta ha sido frecuentemente nominada como canónica para las personas que intentan usarla sh
y se sorprenden de que no se comporta igual que bash
. A continuación se ofrece un resumen rápido de los malentendidos y errores más comunes.
En primer lugar, debes entender qué esperar.
- Si ejecuta su script con
sh scriptname
, o lo ejecuta conscriptname
y tiene#!/bin/sh
en la línea shebang , debe esperarsh
un comportamiento POSIX. - Si ejecuta su script con
bash scriptname
, o lo ejecuta conscriptname
and have#!/bin/bash
(o el equivalente local) en la línea shebang, debería esperar un comportamiento de Bash.
Tener un shebang correcto y ejecutar el script escribiendo solo el nombre del script (posiblemente con una ruta relativa o completa ) es generalmente la solución preferida. Además de un shebang correcto, esto requiere que el archivo de script tenga permiso de ejecución ( chmod a+x scriptname
).
Entonces, ¿en qué se diferencian realmente?
Bash pretende ser compatible con versiones anteriores de Bourne Shell y POSIX, pero tiene muchas características adicionales. El manual de referencia de Bash tiene una sección que intenta enumerar las diferencias , pero algunas fuentes comunes de confusión incluyen
[[
no está disponible ensh
(solo[
cuál es más complicado y limitado). Ver también Diferencia entre corchetes simples y dobles en Bashsh
no tiene matrices.- Algunas palabras clave de Bash como
local
,source
,function
,shopt
,let
,declare
yselect
no son portátiles parash
. (Algunassh
implementaciones admiten, por ejemplolocal
). - Bash tiene muchas extensiones de sintaxis de estilo C, como el bucle de tres argumentos
for((i=0;i<=3;i++))
,+=
la asignación incremental, etc. La$'string\nwith\tC\aescapes'
característica se acepta provisionalmente para POSIX (lo que significa que ahora funciona en Bash, pero aún no será compatible consh
sistemas que solo se adhieren a la versión actual). especificación POSIX, y probablemente no lo hará durante algún tiempo). - Soportes de bash
<<<'here strings'
. - Bash tiene
*.{png,jpg}
una{0..12}
expansión de llaves. - Bash tiene funciones globales extendidas como
**
(globstar
) para subdirectorios recurrentes yextglob
para usar una sintaxis de comodines diferente y más versátil. Esto está en POSIX, pero es posible que falte en algunas~
se refiere$HOME
solo en Bash (y más generalmente~username
al directorio de inicio deusername
)./bin/sh
implementaciones anteriores a POSIX.- Bash tiene sustitución de procesos con
<(cmd)
y>(cmd)
. - Bash tiene alias de redirección de conveniencia estilo Csh como
&|
for2>&1 |
y&>
for> ... 2>&1
- Bash admite coprocesos con
<>
redirección. - Bash presenta un rico conjunto de expansiones de parámetros no estándar ampliadas, como
${substring:1:2}
,,${variable/pattern/replacement}
conversión de casos, etc. - Bash ha ampliado significativamente las funciones para la aritmética de shell (aunque todavía no tiene soporte para punto flotante). Existe una
$[expression]
sintaxis heredada obsoleta que, sin embargo, debería reemplazarse con$((expression))
sintaxis aritmética POSIX. (sh
Sin embargo, es posible que algunas implementaciones heredadas anteriores a POSIX no lo admitan). - Varios comandos integrados tienen opciones que no son portátiles, como
type -a
,printf -v
y el perenneecho -e
. - Las variables mágicas como
$RANDOM
,$_
, y$SECONDS
son extensiones de Bash. Consulte el Manual de referencia.$PIPESTATUS[@]
$FUNCNAME
- Bash expone algunas instalaciones del sistema como identificadores de archivos, como
/dev/stdin
,/dev/fd/<number>
,/dev/tcp/<network address>
etc. - diferencias sintácticas como
export variable=value
y[ "x" == "y" ]
que no son portátiles (comparación de cadenas portátilesexport variable
debe estar separado de la asignación de variables, y[ ... ]
utiliza un único signo igual). - Muchas, muchas extensiones exclusivas de Bash para habilitar o deshabilitar comportamientos opcionales y exponer el estado interno del shell.
- Muchas, muchas funciones convenientes para uso interactivo que, sin embargo, no afectan el comportamiento del script.
Recuerde, esta es una lista abreviada. Consulte el manual de referencia para obtener la primicia completa y http://mywiki.wooledge.org/Bashism para conocer muchas buenas soluciones; y/o pruebe http://shellcheck.net/ que advierte sobre muchas funciones exclusivas de Bash.
Un error común es tener una #!/bin/bash
línea shebang, pero luego usarla sh scriptname
para ejecutar el script. Básicamente, esto desactiva cualquier funcionalidad exclusiva de Bash, por lo que se obtienen errores de sintaxis, por ejemplo, al intentar utilizar matrices. (La línea shebang es sintácticamente un comentario, por lo que simplemente se ignora en este escenario).
Desafortunadamente, Bash no avisará cuando intente utilizar estas construcciones cuando se invoque como sh
. Tampoco deshabilita completamente todas las funciones exclusivas de Bash, por lo que ejecutar Bash invocándolo sh
no es una buena manera de verificar si su script es portátil correctamente a ash
/ dash
/POSIX sh
o variantes como Heirloomsh
. Si desea verificar el cumplimiento estricto de POSIX, intente posh
en su modo POSIX designado (que, sin embargo, no parece estar documentado adecuadamente).
Además, el esfuerzo de estandarización de POSIX tiene como objetivo especificar el comportamiento de varios comportamientos de plataforma similares a U*x, incluido el shell ( sh
). Sin embargo, este es un documento en evolución y, por lo tanto, algunas implementaciones se adhieren a una versión anterior de la especificación POSIX; Además, hay algunas implementaciones heredadas que ni siquiera intentaron cumplir con POSIX. El shell Bourne original tenía algunas peculiaridades que luego fueron corregidas por la especificación POSIX, que en gran parte se basa en ksh88
. (Muchas de las extensiones de Bash también son innovaciones de ksh
.)
Shell es una interfaz entre un usuario y un sistema operativo para acceder a los servicios de un sistema operativo. Puede ser GUI o CLI (interfaz de línea de comando).
sh (Bourne sh ell) es un intérprete de línea de comandos de shell para sistemas operativos Unix/tipo Unix. Proporciona algunos comandos integrados. En lenguaje de programación denotamos intérprete como #!/bin/sh
. Era uno de los más soportados por otros shells como bash (gratis/abierto), kash (no gratuito).
Bash ( Bourne a win s hell) es un reemplazo del shell Bourne . Bash es un superconjunto de sh. Bash admite sh. POSIX es un conjunto de estándares que definen cómo deberían funcionar los sistemas compatibles con POSIX. Bash no es en realidad un shell compatible con POSIX. En un lenguaje de programación denotamos al intérprete como .#!/bin/bash
Analogía:
- Shell es como una interfaz, especificaciones o API.
- sh es una clase que implementa la interfaz Shell.
- Bash es una subclase de sh.
Publicación de UNIX.COM
Características de la carcasa
La siguiente tabla enumera la mayoría de las características que creo que te harían elegir un shell sobre otro. No pretende ser una lista definitiva y no incluye todas las características posibles para cada shell posible. Solo se considera que una característica está en un shell si está en la versión que viene con el sistema operativo o si está disponible compilada directamente desde la distribución estándar. En particular, el shell C especificado a continuación es el disponible en SUNOS 4.*, un número considerable de proveedores ahora envían tcsh o su propio shell C mejorado (no siempre dejan en claro que están enviando tcsh).
Código:
sh csh ksh bash tcsh zsh rc es
Job control N Y Y Y Y Y N N
Aliases N Y Y Y Y Y N N
Shell functions Y(1) N Y Y N Y Y Y
"Sensible" Input/Output redirection Y N Y Y N Y Y Y
Directory stack N Y Y Y Y Y F F
Command history N Y Y Y Y Y L L
Command line editing N N Y Y Y Y L L
Vi Command line editing N N Y Y Y(3) Y L L
Emacs Command line editing N N Y Y Y Y L L
Rebindable Command line editing N N N Y Y Y L L
User name look up N Y Y Y Y Y L L
Login/Logout watching N N N N Y Y F F
Filename completion N Y(1) Y Y Y Y L L
Username completion N Y(2) Y Y Y Y L L
Hostname completion N Y(2) Y Y Y Y L L
History completion N N N Y Y Y L L
Fully programmable Completion N N N N Y Y N N
Mh Mailbox completion N N N N(4) N(6) N(6) N N
Co Processes N N Y N N Y N N
Builtin artithmetic evaluation N Y Y Y Y Y N N
Can follow symbolic links invisibly N N Y Y Y Y N N
Periodic command execution N N N N Y Y N N
Custom Prompt (easily) N N Y Y Y Y Y Y
Sun Keyboard Hack N N N N N Y N N
Spelling Correction N N N N Y Y N N
Process Substitution N N N Y(2) N Y Y Y
Underlying Syntax sh csh sh sh csh sh rc rc
Freely Available N N N(5) Y Y Y Y Y
Checks Mailbox N Y Y Y Y Y F F
Tty Sanity Checking N N N N Y Y N N
Can cope with large argument lists Y N Y Y Y Y Y Y
Has non-interactive startup file N Y Y(7) Y(7) Y Y N N
Has non-login startup file N Y Y(7) Y Y Y N N
Can avoid user startup files N Y N Y N Y Y Y
Can specify startup file N N Y Y N N N N
Low level command redefinition N N N N N N N Y
Has anonymous functions N N N N N N Y Y
List Variables N Y Y N Y Y Y Y
Full signal trap handling Y N Y Y N Y Y Y
File no clobber ability N Y Y Y Y Y N F
Local variables N N Y Y N Y Y Y
Lexically scoped variables N N N N N N N Y
Exceptions N N N N N N N Y
Clave de la tabla anterior.
La función Y se puede realizar usando este shell.
N La característica no está presente en el shell.
La función F solo se puede realizar utilizando el mecanismo de función de shells.
L La biblioteca readline debe estar vinculada al shell para habilitar esta función.
Notas a la tabla anterior
- Esta característica no estaba en la versión original, pero desde entonces se ha convertido casi en estándar.
- Esta característica es bastante nueva y, por lo tanto, a menudo no se encuentra en muchas versiones del shell; gradualmente se está abriendo camino en la distribución estándar.
- Muchos piensan que la emulación Vi de este shell está incompleta.
- Esta función no es estándar, pero existen parches no oficiales para realizarla.
- Una versión llamada 'pdksh' está disponible gratuitamente, pero no tiene la funcionalidad completa de la versión de AT&T.
- Esto se puede hacer a través del mecanismo de finalización programable del shell.
- Solo especificando un archivo a través de la variable de entorno ENV.