Introducción al intérprete de comandos
El intérprete de comandos permite la comunicación entre el sistema y el usuario. Aunque actualmente las interficies gráficas de usuario (GUI) facilitan el trabajo cotidiano, todavía existen funciones, como la automatización de tareas, que se resuelven mejor desde la línea de comandos (CLI Command Line Interface).
Las ventajas evidentes de la línea de comandos frente a la interfaz gráfica son:
- Mayor capacidad de expresión semántica
- Menor consumo de recursos (muy importante si se actúa sobre sistemas remotos mediante una conexión lenta)
- Posibilidad de programar guiones o scripts.
- Programas y sintáxis enfocada a conseguir una mayor productividad
Entre los inconvenientes:
- El usuario precisa de un aprendizaje previo
- Funcionamiento menos intuitivo
Existen
multitud de intérpretes de comandos, en algunos sistemas operativos puede haber varios
instalados y cada usuario decide cuál utilizar.
Algunos ejemplos:
Unix | Windows |
---|---|
Korn Shell (ksh) C Shell (csh) Bourne Shell (sh) Bourne Again Shell (bash) Tcsh Z Shell (Zsh) | command.com cmd.exe MSH Windows PowerShell (Monad) |
Entre los shells más destacados, encontramos:
- Command.com y cmd.exe
- Intérprete de comandos presente en los sistemas operativos Windows 95, 98, 98 SE y Me. Está basado en la sintáxis de MS-DOS y puede funcionar tanto en modo interactivo como ejecutando archivos por lótes (.BAT). La versión de Windows NT, 2000, XP y 2003 es cmd.exe aunque también esté presente la antigua por compatibilidad.
- MSH Windows PowerShell (Monad)
- Nuevo shell de Microsoft presentado con Windows Vista y también disponible en XP, requiere el marco de trabajo .NET. Entre sus nuevas características se encuentra el autocompletado (al pulsar el tabulador).
- Bourne Again Shell (Bash)
- Versión
de shell que se utiliza por defecto en la mayoría de las distribuciones
GNU/Linux, OpenSolaris o en MacOSX. Está basado en el tradicional Bourne Shell y
aporta nueva características. Forma parte del proyecto GNU.
Características de Bash
Bash es el intérprete de comandos que se desarrolló en 1987 para el proyecto GNU, su nombre hace referencia al conocido shell Bourne Shell y toma ideas de otros shells como Korn Shell y C Shell.
Bash puede
utilizarse como intérprete de comandos en modo interactivo, pero
también puede procesar archivos con órdenes. A estos archivos
ejecutables se les llama guiones o, en inglés, scripts. Cuando se utiliza un intérprete
como Bash no es necesario compilar el código fuente. El intérprete es
capaz de interpretar el código fuente sentencia a sentencia. El tiempo
de desarrollo es más corto que con los lenguajes compilados pero el tiempo de ejecución es
habitualmente mayor.
El espectro de características de Bash es realmente grande. Para una descripción detallada es necesario acudir a la documentación oficial.
Case sensitive
Bash, y en general Unix, distingue entre mayúsculas y minúsculas. No es lo mismo escribir ls que Ls.
Edición con Bash
Utilizado en modo interactivo, Bash ofrece todas las facilidades de la biblioteca Readline. Además, podemos encontrar otras facilidades como el historial de comandos.
Todos
los comandos que se ejecutan se guardan en el historial. Es posible ver
los últimos comandos ejecutados mediante el comando interno history.
Utilizando las flechas de los cursores (arriba y abajo), es posible
navegar por dicho historial para reutilizar sentencias ya introducidas.
También es posible:
- Utilizar !! para repetir la última sentencia
- Utilizar !200 para repetir el comando que está en la posición 200 del historial
- Utilizar la variable HISTSIZE para definir el tamaño máximo del historial
Otra
de las características de edición de Bash más cómodas, es el
autocompletado de nombres de comandos, ficheros, etc... Símplemente es
necesario escribir las primeras letras y pulsar la tecla TAB
para que el shell complete lo que estamos escribiendo. Si lo que hemos
escrito puede completarse de diferentes maneras, al pulsar dos veces la
tecla TAB nos mostrará las alternativas.
Expansión de nombres de ficheros
Es
posible indicar patrones de coincidencia para los nombres de los
ficheros. De este modo, un patrón puede referirse a muchos ficheros
diferentes (todos aquellos con un nombre que concuerda con el patrón).
En la expansión de nombres de ficheros, Bash utiliza patrones formados por los carácteres ?, * y [ de la siguiente manera:
- ?
- Coincide con cualquier carácter (sólo uno)
- *
- Coincide con cualquier cadena, incluyendo a la cadena nula
- [...]
- Coincide con cualquiera de los carácteres enumerados entre los corchetes (por ejemplo [aeiou] coincide con cualquier vocal). Si se utiliza un guión se pueden incluir rangos (por ejemplo [a-zA-Z]). También es posible utilizar la sintáxis [:class:] para denotar una clase predefinida de carácter. Las clases predefinidas (POSIX 1003.2) son: alnum, alpha, ascii, blank, cntrl, digit, graph, lower, print, punct, space, upper, word, xdigit. Si el primer carácter entre corchetes es la admiración !, entonces entre los corchetes se enumeran los carácteres que no deben existir.
Ejemplos:
patrón | Coincide con |
---|---|
* | Cualquier nombre |
*rpm | Nombres que finalizan en 'rpm' |
???datos*dt | Nombres que comienzan con tres carácteres cualesquiera, les sigue la cadena 'datos', luego pueden tener cualquier cadena (o no) y han de acabar en 'dt' |
[aeiou]???.jpg | Nombres que comienzan con una vocal en minúscula, seguidos de tres carácteres y la cadena '.jpg' |
Fichero[!a-z] | Nombres que comienzan con 'Fichero' seguido de cualquier carácter que no sea una letra minúscula |
Expansión de llaves
La expansión de llaves, Brace Expansion,
es similar a la expansión de nombres de ficheros. Nos sirve para
teclear menos. Pero en este caso, los patrones generan cadenas que no
necesariamente han de existir.
Ejemplos:
[vcarceler@localhost pruebas]$ echo Fichero-{1,2,3,4,5}
Fichero-1 Fichero-2 Fichero-3 Fichero-4 Fichero-5
[vcarceler@localhost pruebas]$ echo directorio/{gráficos,juegos}/bin/{*.exe,*.jpg}
directorio/gráficos/bin/*.exe directorio/gráficos/bin/*.jpg directorio/juegos/bin/*.exe directorio/juegos/bin/*.jpg
Ni las llaves ni las comas pueden ir entre comillas.
Alias
Es
posible definir palabras que se substituirán por sentencias a nuestra
conveniencia. Por ejemplo, para hacer que el shell interprete "ls -lia" cada vez que nosotros escribamos listado, podemos hacer:
alias listado="ls -lia"
Si se utiliza el comando interno alias sin argumentos se muestra la lista de alias definidos. Mediante el comando interno unalias
se pueden borrar alias definidos. Un alias dura mientras está activa la
sesión en la que se definió. Al cerrar el shell y abrir uno nuevo no
estará definido. Si se quiere disponer de un determinado alias en cada sesión, será necesario definirlo en los ficheros de inicialización de Bash, típicamente ~/.bashrc.
Variables de entorno
Las
variables de entorno son porciones de memoria que guardan datos. Estas
variables pueden ser locales a la instáncia del shell que se está
utilizando o bien globales a todos sus subshells. En Bash las
variables de entorno tienen un nombre alfanumérico. Para referirse al
valor de la variable se utiliza el carácter dólar $ como prefijo del
nombre.
Por ejemplo:
[vcarceler@localhost ~]$ echo $saludo -> Se accede a una variable no
-> inicializada.
[vcarceler@localhost ~]$ saludo="Hola, cómo va todo ?" -> Se asigna valor a 'saludo'
[vcarceler@localhost ~]$ echo $saludo -> Se comprueba el valor
Hola, cómo va todo ?
[vcarceler@localhost ~]$ export saludo="Hola ?" -> Se exporta la variable a este shell
[vcarceler@localhost ~]$ -> y a sus descendientes.
Como los alias, las variables de entorno sólo viven mientras vive el intérprete de comandos en el que fueron declaradas, al terminar la sesión pierden su valor.
Comandos internos relacionados:
- export [variable]
- Variables a exportar a los subshells. A no ser que se exporten de manera explícita cada shell tiene sus propias variables de entorno.
- unset [variable]
- Libera la memoria de la variable indicada, de modo que esta deja de existir.
- env
- Muestra un listado de todas las variables de entorno definidas.
Algunas variables de entorno importantes son:
- PATH
- Guarda una lista de directorios (separados por el carácter ':') en los que se van a buscar los programas a ejecutar. El órden en la lista es importante. Si se llega al final de la lista sin encontrar el comando buscado por el usuario, entonces el shell presenta un mensaje de error al usuario.
- HOME
- Guarda la ruta del directorio de conexión para el usuario.
- PWD
- Guarda la ruta del directorio actual
- DISPLAY
- Guarda el identificador del escritorio en el que se intentarán abrir las ventanas de los programas que ejecutamos.
- PROMPT_COMMAND
- Si está definida, y su valor no es nulo, se supone que contiene una sentencia que el shell ejecuta automáticamente después de ejecutar lo que el usuario le manda.
- PS1, PS2, PS3 y PS4
- Definen el prompt del sistema. Puede consultar una lista de códigos de control para modificar el prompt.
- RANDOM
- Cada vez que se consulta su valor, se obtiene un número pseudoaleatorio entre 0 y 32767. Al fijar su valor se planta la semilla (seed) del generador de números pseudoaleatorios.
- SECONDS
- Al consultar su valor se obtiene el número de segundos desde que el shell se inició.
Comillas
En
Bash las comillas se utilizan para delimitar cadenas que tienen
espacios (o tabuladores, o sáltos de línea). Si un fichero tiene un
nombre con espacios, debe entrecomillarse.
Tipos de comillas:
- Comilla símple (apóstrofe ')
- La comilla símple delimita cadenas en las que no se realiza interpolación de variables. Es decir, no se substituyen por su contenido.
- Comilla doble (")
- Delimita cadenas en las que se realiza interpolación de variables. Se substituyen por su contenido.
- Comilla invertida (acento abierto `)
- Delimita cadenas que se suponen sentencias para el shell. El shell las ejecuta y retorna el resultado. Se realiza interpolación de variables.
Ejemplos:
[vcarceler@localhost ~]$ color_favorito=rojo
[vcarceler@localhost ~]$ echo 'Mi color favorito es $color_favorito'
Mi color favorito es $color_favorito
[vcarceler@localhost ~]$ echo "Mi color favorito es $color_favorito"
Mi color favorito es rojo
[vcarceler@localhost ~]$ listado=`ls -a .`
[vcarceler@localhost ~]$ directorio=/
[vcarceler@localhost ~]$ listado=`ls $directorio`
[vcarceler@localhost ~]$ echo $listado
bin/ boot/ dev/ etc/ home/ initrd/ lib/ lost+found/ mnt/ opt/ proc/ root/ sbin/ sys/ tmp/ usr/ var/
[vcarceler@localhost ~]$
Escapando carácteres
Ya se ha visto que algunos carácteres tienen un significado especial para el shell, por ejemplo los carácteres: ?, *, [, ], $, ', ", `,
... o el espacio ' ' que actúa como separador de palábras. Cuando se
quiere desposeer a uno de estos carácteres de su significado especial,
se utiliza la contrabarra \ (que evidentemente es un carácter especial) para escaparlos.
Ejemplos:Comando Función ls * Listar todos los ficheros (se llamen como se llamen) ls \* Listar el fichero que tiene por nombre '*' ls Hola que tal? Listar los ficheros: Hola, que y todos aquellos que comienzan por
'tal' seguido de cualquier otro carácterls Hola\ que\ tal\? Listar el fichero que se llama textualmente 'Hola que tal?'
Redirecciónes de entrada/salida
En el shell existen tres flujos de entrada/salida:
- La salida standard (stdout)
- Es el lugar en el que se presenta la salida, a no ser que se indique lo contrario. La salida standard es la cónsola en la que se está trabajando.
- La entrada standard (stdin)
- Es el lugar del que se leen datos a no ser que se indique lo contrario. Por defecto, es el teclado.
- La salida de error (stderr)
- Es el lugar en el que se presentan los mensajes de error a no ser que se indique lo contrario. La salida de error por defecto apunta a la cónsola en la que se está trabajando.
Es posible redirigir cada una de ellas:
# Redirección de stdout hacia un fichero de nombre salida (redirección destructiva)
echo "hola" >salida
# Igual, pero sin destruir (añadiendo datos al fichero)
echo "adios" >>salida
# Redirección de la salida de error a un fichero (destructiva)
cat $fichero 2>salida_error
# Redirección de la salida de error no destructiva
cat $fichero 2>>salida_error
# Redirección de stdin hacia un fichero
less </etc/passwd
Tuberias (pipes)
Bash
permite ejecutar varios programas, en procesos diferentes, a la vez. De
tal manera que la salida y la entrada de estos procesos queda conectada
formando una cadena.
Ejemplos:
cat /etc/passwd | less
cat /etc/passwd | grep /bin/bash | wc -l
Ficheros de control de Bash
Si existen los ficheros .bash_profile y .bashrc, que permiten configurar automáticamente el entorno de ejecución, se leen e interpretan cada vez que se invoca al intérprete de comandos Bash. En estos ficheros pondremos la definición de todos los alias y de todas las variables de entorno que esperemos encontrar en cada una de nuestras sesiones de trabajo.
También puede existir el fichero .bash_logout, que sería interpretado al cerrar la sesión de trabajo.
Estos ficheros pueden encontrarse en:
- En /etc/profile
- Con lo que resultan de aplicación para cualquier usuario
- En el directorio personal ~ (/home/usuarioX)
- Con lo que sólo se aplican a las sesiones del usuario
Cuando se invoca Bash, se tiene en cuenta si:
- Se trata de un shell interactivo:
- Un shell interactivo es un shell en el que el usuario escribe comandos y estos son ejecutados. Un shell no interactivo es aquel que se invoca para interpretar un shell script (trabajo por lotes).
- Se trata de un login shell:
- Un login shell es aquel que dá la bienvenida al sistema y se ejecuta automáticamente al identificarse con el nombre de usuario y la contraseña.
Casos:
- Si se trata de un shell interactivo de tipo login (o se ha utilizado la opción --login) se leerá e interpretará (si existe y es legible) el contenido de /etc/profile. Después buscará (en el orden especificado) e interpretará el primer fichero que exista y sea legible de los siguientes: ~/.bash_profile, ~/.bash_login, ~/.profile
- Si se trata de un shell interactivo que no es de tipo login se buscará e interpretará (si existe y es legible) el fichero ~/.bashrc
- Si
se trata de un shell no interactivo, Bash utiliza el contenido de la
variable de entorno BASH_ENV para encontrar el fichero de
inicialización. Es decir, la variable de entorno deberá contener la
ruta absoluta del fichero a utilizar.