Un shell, en su esencia, es un procesador de macros que ejecuta comandos. En este contexto, un "procesador de macros" se refiere a una funcionalidad que expande texto y símbolos para crear expresiones más complejas.
En el entorno Unix, un shell cumple dos roles fundamentales: actúa como intérprete de comandos y como lenguaje de programación. Como intérprete de comandos, el shell proporciona una interfaz de usuario para un conjunto amplio de utilidades GNU. Además, el shell permite combinar estas utilidades mediante características de lenguaje de programación, permitiendo la creación de archivos de comandos que, a su vez, se convierten en comandos ejecutables con el mismo estatus que los comandos del sistema ubicados en directorios como /bin. Esto facilita la personalización del entorno para automatizar tareas comunes.
Los shells pueden operarse en dos modos: interactivo y no interactivo. En el modo interactivo, el shell acepta entradas directamente desde el teclado, permitiendo al usuario ejecutar comandos en tiempo real. En contraste, en el modo no interactivo, el shell ejecuta comandos leídos desde un archivo, lo que es útil para automatizar procesos o ejecutar scripts predefinidos.
El shell permite la ejecución de comandos GNU de forma sincrónica y asincrónica. Los comandos sincrónicos hacen que el shell espere a que el comando termine antes de aceptar más entradas, mientras que los comandos asincrónicos continúan ejecutándose en paralelo mientras el shell procesa otras órdenes. Las construcciones de redirección ofrecen un control detallado sobre las entradas y salidas de los comandos, y el shell también proporciona control sobre el entorno en el que se ejecutan estos comandos.
Además, los shells ofrecen un conjunto pequeño de comandos incorporados (builtins) que implementan funcionalidades que serían imposibles o inconvenientes de obtener a través de utilidades separadas. Por ejemplo, comandos como cd
, break
, continue
y exec
no pueden ser implementados fuera del shell porque manipulan directamente el shell mismo. Otros builtins, como history
, getopts
, kill
o pwd
, podrían implementarse en utilidades separadas, pero resultan más convenientes como comandos incorporados.
Aunque la ejecución de comandos es crucial, gran parte del poder y complejidad de los shells proviene de sus lenguajes de programación integrados. Al igual que cualquier lenguaje de alto nivel, el shell ofrece variables, constructores de control de flujo, comillas y funciones.
Además de sus capacidades de programación, los shells ofrecen características específicas para el uso interactivo. Estas características incluyen control de trabajos, edición de línea de comandos, historial de comandos y alias. Cada una de estas funciones está diseñada para mejorar la experiencia del usuario y facilitar la gestión eficiente del entorno de comandos.