Bash

GNU Bash o simplemente Bash (Bourne-again shell) es una interfaz de usuario de línea de comandos popular, específicamente un shell de Unix; así como un lenguaje de scripting. Bash fue originalmente escrito por Brian Fox para el sistema operativo GNU, y pretendía ser el reemplazo de software libre del shell Bourne. Lanzado por primera vez en 1989, se ha utilizado ampliamente como el intérprete de inicio de sesión (login) predeterminado para la mayoría de las distribuciones de GNU/Linux, y también de Mac OS X de Apple hasta la versión 10.15. Una versión también está disponible para Windows 10 y Android. También es el intérprete de órdenes de usuario predeterminado en Solaris 11.

Bash es un intérprete de órdenes que generalmente se ejecuta en una ventana de texto donde el usuario escribe órdenes en modo texto. Bash también puede leer y ejecutar órdenes desde un archivo, llamado guion o 'script', que son secuencias de comandos escritas en el lenguaje de scripting de Bash. Estos scripts permiten automatizar tareas y combinar comandos y estructuras de control en un solo archivo. Al igual que todos los intérpretes de Unix, es compatible con el agrupamiento de nombres de archivo (coincidencia de comodines), tuberías, here documents, sustitución de comandos, variables y estructuras de control para pruebas de condición e iteración. Las palabras reservadas, la sintaxis, las variables de ámbito dinámico y otras características básicas del lenguaje se copian de sh. Otras características, por ejemplo, el historial, se copian de csh y ksh. Bash es un intérprete de órdenes compatible con POSIX, pero con varias extensiones.

El nombre del intérprete es un acrónimo de 'Bourne-again shell' (intérprete de órdenes Bourne, de nuevo), un juego de palabras con el nombre del intérprete Bourne que reemplaza y la noción de "nacer de nuevo" (born-again).

Un agujero de seguridad en Bash que data de la versión 1.03 (agosto de 1989), denominado Shellshock, fue descubierto a principios de septiembre de 2014 y recibió amplia atención de los medios. Rápidamente provocó una serie de ciberataques en Internet. Los parches para corregir los errores se pusieron a disposición poco después de que se identificaron los errores.

Historia 
Brian Fox comenzó a codificar Bash el 10 de enero de 1988 después de que Richard Stallman se sintiera insatisfecho con la falta de progreso de un desarrollador anterior. Stallman y la Free Software Foundation (FSF) consideraron un intérprete libre que podría ejecutar scripts de shell existentes tan estratégicos para un sistema completamente libre construido a partir de código BSD y GNU que este fue uno de los pocos proyectos que financiaron ellos mismos, con Fox emprendiendo el trabajo como un empleado de FSF. Fox lanzó Bash como beta, versión .99, el 8 de junio de 1989 y se mantuvo como el colaborador principal hasta mediados de 1992 y mediados de 1994, cuando fue despedido de la FSF y su responsabilidad fue transferida a otro colaborador temprano, Chet Ramey.

Desde entonces, Bash se ha convertido en el shell más popular entre los usuarios de las distribuciones GNU/Linux, convirtiéndose en el shell interactivo predeterminado en las diversas distribuciones GNU/Linux(con distribuciones se refiere a todo sistema operativo que como kernel tenga el kernel de linux) (aunque el intérprete Almquist puede ser el intérprete de secuencias de órdenes predeterminado) y en las versiones de MacOS de Apple antes de Catalina en octubre de 2019. Bash también ha sido importado a Microsoft Windows y distribuido con Cygwin y MinGW, a DOS por el proyecto DJGPP, a Novell NetWare y a Android a través de varias aplicaciones de emulación de terminal.

En septiembre de 2014, Stéphane Chazelas, especialista en Unix / Linux, descubrió un error de seguridad en el programa. El error, revelado por primera vez el 24 de septiembre, se llamó Shellshock y se le asignaron los números CVE-2014-6271, CVE-2014-6277 y CVE-2014-7169. El error se consideró grave, ya que los scripts CGI que usan Bash podrían ser vulnerables, lo que permite la ejecución de código arbitrario. El error estaba relacionado con la forma en que Bash pasa las definiciones de funciones a subcapas a través de variables de entorno.

Scripts Bash 

Los scripts en informática son utilizados para manipular, personalizar y automatizar instalaciones de sistemas existentes. Se almacenan en archivos de texto y se interpretan línea por línea en tiempo real para su ejecución. Por lo general, tienen la extensión .sh y comienzan con un shebang, que indica qué shell debe interpretar ese script.

Los archivos de órdenes en Bash se conocen como procedimientos shell, archivos shell o guiones shell (scripts en inglés). Los scripts Bash permiten automatizar tareas repetitivas o complejas al combinar comandos y estructuras de control en un solo archivo. Estos scripts pueden ser ejecutados desde la línea de comandos o programados para ejecutarse automáticamente en momentos específicos. 
 
Los archivos script en Bash se identifican a través del shebang #!/bin/bash, que especifica Bash como el intérprete de shell a utilizar.

Sintaxis de Bash 

La sintaxis de órdenes de Bash es un superconjunto de instrucciones basadas en la sintaxis del intérprete Bourne. La especificación definitiva de la sintaxis de órdenes de Bash, puede encontrarse en el Bash Reference Manual distribuido por el proyecto GNU. Esta sección destaca algunas de sus únicas características.

La mayoría de los guiones de intérprete de órdenes Bourne ('shell scripts) pueden ejecutarse por Bash sin ningún cambio, con la excepción de aquellos guiones del intérprete de órdenes, o consola, Bourne que hacen referencia a variables especiales de Bourne o que utilizan una orden interna de Bourne. La sintaxis de órdenes de Bash incluye ideas tomadas desde los intérpretes Korn shell (ksh) y C shell (csh), como la edición de la línea de órdenes, el historial de órdenes, la pila de directorios, las variables $RANDOM y $PPID, y la sintaxis de substitución de órdenes POSIX: $(...). Cuando se utiliza como un intérprete de órdenes interactivo, Bash proporciona autocompletado de nombres de programas, nombres de archivos, nombres de variables, etc., cuando el usuario pulsa la tecla TAB.

La sintaxis de Bash tiene muchas extensiones que no proporciona el intérprete Bourne. Varias de las mencionadas extensiones se enumeran a continuación.

 Acceso a los argumentos 

Los guiones de Bash reciben los argumentos que le pasa al intérprete como $1, $2, …, $n. Se puede obtener el número total de argumentos con el símbolo $#.

Usando $# es posible comprobar el número de argumentos entregados al guion antes de realizar alguna acción con ellos:

 if [ $# -lt 2 ]; then
   echo "Necesitas pasar dos argumentos."
   exit 1
 fi

Otra forma de acceder a los argumentos es a través del array $@, por medio del cual se puede iterar sobre todos los argumentos dados:

  for arg in "$@"
  do
    echo "$arg"
  done

 Operaciones matemáticas con enteros 

Una gran limitación del intérprete Bourne es que no puede realizar cálculos con enteros sin lanzar un proceso externo. En cambio, un proceso Bash puede realizar cálculos con enteros utilizando la orden ((...)) y la sintaxis de variables $[...] de la siguiente manera:

 VAR=55             # Asigna el valor entero 55 a la variable VAR.
 ((VAR = VAR + 1))  # Suma uno a la variable VAR. Observe la ausencia del carácter '$'.
 ((++VAR))          # Otra forma de sumar uno a VAR. Preincremento estilo C.
 ((VAR++))          # Otra forma de sumar uno a VAR. Postincremento estilo C.
 echo $[VAR * 22]   # Multiplica la variable VAR por 22 y sustituye la orden por el resultado.
 echo $((VAR * 22)) # Otra forma de realizar lo mismo.

La orden ((...)) también se puede utilizar en sentencias condicionales, ya que su código de retorno es 0 o 1 dependiendo de si la condición es cierta o falsa:

 if ((VAR == Y * 3 + X * 2))
 then
         echo Si
 fi
 
 ((Z > 23)) && echo Si

La orden ((...)) soporta los siguientes operadores relacionales: '==', '!=', '>', '<', '>=', y '<='.

Un proceso Bash no puede realizar cálculos en coma flotante. Los únicos intérpretes Unix capaces de esto son Korn Shell (versión de 1993) y zsh (a partir de la versión 4.0).

 Redirecciones de entrada/salida 

La sintaxis de Bash permite diferentes formas de redirección de entrada/salida de las que el intérprete Bourne tradicional carece. Bash puede redirigir la salida estándar y los flujos de error estándar a la vez utilizando la sintaxis:

 orden >& archivo

que es más simple que teclear la orden Bourne equivalente, "orden > archivo 2>&1". Desde la versión 2.05b, Bash puede redirigir la entrada estándar desde una cadena utilizando la siguiente sintaxis (denominada "here strings"):

 orden <<< "cadena a leer como entrada estándar"

Si la cadena contiene espacios en blanco, deben utilizarse comillas.

Ejemplo:
Redirige la salida estándar a un archivo, escribe datos, cierra el archivo y reinicia stdout

 # hace que el descriptor de archivo 6 sea una copia de stdout (descriptor archivo 1)
 exec 6>&1
 # abre el archivo "test.data" para escritura
 exec 1>test.data
 # genera algún contenido
 echo "data:data:data"
 # recupera stdout original, al hacer que sea una copia del descriptor de archivo 6
 exec 1>&6
 # cierra el descriptor de archivo 6
 exec 6>&-

Abre y cierra archivos

 # abre el archivo test.data para lectura
 exec 6<test.data
 # lee hasta el final del archivo
 while read -u 6 dta
 do
   echo "$dta" 
 done
 # cierra el archivo test.data
 exec 6<&-

Captura la salida de órdenes externas

  # ejecuta 'find' y guarda los resultados en VAR
  # busca nombres de archivos que terminan con la letra "h"
  VAR=$(find . -name "*h")

 Expresiones regulares 

Los procesos Bash 3.0 soportan emparejamiento de expresiones regulares utilizando la siguiente sintaxis, reminiscente de Perl:

 [[ string =~ regex]] 

La sintaxis de expresiones regulares es la misma que documenta la página de manual regex(3). El estado de salida de la orden anterior es 0 si la cadena concuerda con la expresión regular, y 1 si no coinciden.
En las expresiones regulares puede accederse a las partes delimitadas por paréntesis, utilizando la variable shell BASH_REMATCH, de la siguiente manera:

 if [[ foobarbletch =~ 'foo(bar)bl(.*)']] 
 then
         echo The regex matches!
         echo $BASH_REMATCH      -- outputs: foobarbletch
         echo ${BASH_REMATCH[1]} -- outputs: bar
         echo ${BASH_REMATCH[2]} -- outputs: etch
 fi

Esta sintaxis proporciona un rendimiento superior a lanzar un proceso separado para ejecutar una orden grep, porque el emparejamiento de las expresiones regulares tiene lugar en el propio proceso Bash. Si la expresión regular o la cadena contiene un espacio en blanco o un metacarácter del intérprete (como '*' o '?'), debe ser entrecomillada.

 Escape con contrabarra 

Las palabras con la forma $'string' se tratan de un modo especial. Estas palabras se expanden a string, con los caracteres escapados por la contrabarra reemplazados según especifica el lenguaje de programación C. Las secuencias de escape con contrabarra, se decodifican del siguiente modo:

El resultado expandido se encuentra entrecomillado con comilla simple, como si el signo $ no estuviese presente.

Una cadena entrecomillada con comillas dobles precedida por un signo $ ($"...") será traducida de acuerdo a la localización actual. Si fuese C o POSIX, se ignora el símbolo $. Si la cadena es traducida y reemplazada, el reemplazo estará entrecomillado por comilla doble.

 Guiones de inicio de Bash 

Cuando Bash arranca, ejecuta las órdenes que se encuentran en diferentes guiones.

Cuando se invoca a Bash como un intérprete interactivo para el inicio de una sesión (login shell), o como un intérprete no interactivo con la opción --login, en primer lugar lee y ejecuta órdenes desde el archivo /etc/profile, si existe. Después, busca ~/.bash_profile, ~/.bash_login, y ~/.profile, en este orden, y lee y ejecuta las órdenes desde el primero que existe y es legible. La opción --noprofile puede utilizarse al comenzar un nuevo intérprete para inhibir este comportamiento.

Cuando una sesión del intérprete finaliza, Bash lee y ejecuta las órdenes de ~/.bash_logout, si existe.

Cuando un intérprete interactivo que no es un login shell arranca, Bash lee y ejecuta órdenes desde ~/.bashrc, si existiese. Esto puede evitarse utilizando la opción --norc. La opción --rcfile archivo forzará a Bash a leer y ejecutar órdenes desde archivo en lugar de ~/.bashrc.

Cuando Bash arranca de un modo no interactivo, por ejemplo para ejecutar un guion de consola diferente, busca la variable de entorno BASH_ENV, si existe expande su valor, y lo utiliza como el nombre del archivo para leer y ejecutar. Bash se comporta como si se ejecutase la siguiente orden:

 if [ -n "$BASH_ENV" ]; then . "$BASH_ENV"; fi

pero el valor de la variable PATH no se utiliza para buscar el archivo.

Si se invoca a Bash con el nombre sh, intenta replicar el comportamiento de las versiones antiguas de sh, a la vez que se mantiene la conformidad con el estándar POSIX. Cuando se invoca como un inicio de sesión interactivo, o un intérprete no interactivo con la opción --login, primero intenta leer y ejecutar órdenes desde /etc/profile y ~/.profile, en este orden. La opción --noprofile puede utilizarse para evitar este comportamiento.

Cuando se invoca como un inicio de sesión interactivo con el nombre sh, Bash busca la variable ENV, si está definida expande su valor, y utiliza el valor expandido como el nombre de un archivo para leer y ejecutar. Como un intérprete invocado como sh no intenta leer y ejecutar órdenes desde ningún otro archivo de arranque, y la opción --rcfile no tiene efecto. Un intérprete no interactivo invocado con el nombre sh no intenta leer ningún otro archivo de arranque. Cuando se invoca como sh, Bash entra en el modo posix'' después de leer los archivos de inicio.

Cuando se inicia Bash en el modo POSIX, por ejemplo con la opción --posix, sigue el estándar POSIX para los archivos de inicio. En este modo, los intérpretes interactivos expanden la variable ENV y se leen, y ejecutan, las órdenes desde el archivo cuyo nombre es el valor de la variable expandida. No se lee ningún otro archivo de arranque.

Bash intenta determinar cuando está siendo ejecutado por un demonio de intérprete remoto, normalmente rshd. Si Bash determina que está siendo ejecutado por rshd, lee y ejecuta órdenes desde ~/.bashrc, si este archivo existe y es legible. No hará esto si se invoca como sh. La opción --norc puede utilizarse para evitar este comportamiento, y la opción --rcfile puede utilizarse para forzar a leer otro archivo, pero rshd normalmente no invoca al shell con estas opciones o permite que sean especificadas.

Bashismo 
Se llama bashismo al uso de características de Bash que no están contempladas en las especificaciones POSIX para los intérpretes de órdenes. En general, se recomienda evitarlas, para permitir la portabilidad de guiones a otros sistemas operativos.

Véase también 
 Comandos Bash
 Bourne Shell
 Shell (informática)
 GNU/Linux
 Shell de Unix

Referencias

Enlaces externos 

 
 Lista de órdenes
 Bash home page
 
 Bash FAQ
 Bash 3.0 Announcement
 The GNU Bash Reference Manual, (HTML versión) by Chet Ramey and Brian Fox, ISBN 0-9541617-7-7

Guías Bash de Linux Documentation Project:

 Programación Bash
 Bash Guide for Beginners
 BASH Programming - Introduction HOW-TO
 Advanced Bash-Scripting Guide

Otras guías y tutoriales:

 About Shells
 Beginners Bash Tutorial
 Advancing in the Bash Shell tutorial
 Linux Know-How including the Bash Guide for Beginners
 Introducción y ejemplos varios /básicos/medios/avanzados en Bash script

Software del Proyecto GNU
Software para Unix
Software para Linux
Shell de Unix