Indicadores de Logros
- Crea scripts sencillos para bash.
- Emplea variables de ambiente y reconoce algunas empleadas por bash.
- Aprovecha las expansiones que bash realiza.
- Emplea comandos de bash y programas comúnmente usados al hacer scripts.
Un script para bash es un archivo tipo texto, cuyas líneas tienen comandos que son ejecutados (interpretados) por bash. Para lograr que el intérprete de comandos intérprete las líneas de un archivo puede:
- Ejecutar /bin/bash seguido del nombre del archivo (o redireccionar la entrada estándar para que provenga del archivo).
- Emplear el comando source seguido del nombre del archivo.
- Emplear el caracter '.' seguido de un espacio y el nombre del archivo.
- Agregar en la primera línea del archivo la cadena #!/bin/bash, dar permiso de ejecución al archivo y teclear el nombre del archivo desde el intérprete de comandos
como si fuera un nuevo comando.
En este capítulo presentamos algunas facilidades que bash brinda y que resultan muy útiles para escribir scripts. Antes se presentará como ejecuta bash una orden (lo cual en particulars explica porque la primera línea de un script para bash debería ser
#!/bin/bash).
Dado que las facilidades que presentaremos no son exclusivas de scripts sino de bash, puede hacer experimentos desde el intérprete de comandos mientras lee.
Para determinar cual es la orden bash realiza varias acciones:
- Primero realiza ciertas expansiones a la línea de comando, e identifica la orden, los parámetros y eventualmente las variables de ambiente que se den junto con la orden (en esta sección se estudiarán las expansiones y variables de ambiente).
- Si la orden va precedida de una ruta
se trata del nombre completo de un archivo
y el archivo existe y es ejecutable, bash lo trata como un programa y lo carga a memoria para ejecutarlo. Si la ruta no conduce a un archivo ejecutable bash presenta un mensaje de error.
- Si la orden no va precedida de una ruta, busca un alias que pueda corresponder con la orden y si lo encuentra lo remplaza por su valor (más adelante en esta sección explicaremos como manejar alias).
- Si la orden no esta precedida de una ruta y no es un alias, determina si se trata de un comando interno de bash (como fg o bg) y en caso de serlo realiza la acción correspondiente.
- Si la orden no está precedida de una ruta, no es un alias y no es un comando interno busca en varios directorios un archivo ejecutable con el nombre dado y si lo encuentra en alguno lo carga a memoria para ejecutarlo (el orden y los directorios donde busca se especifican en la variable de ambiente PATH que se explicará en esta sección).
- En otro caso bash presenta un mensaje de error.
En caso de que la orden corresponda a un archivo ejecutable (bien porque se dio la ruta completa o bien porque existe un archivo en un directorio de
PATH), bash determinará como ejecutarlo:
- Si el archivo es tipo texto y comienza con la cadena "#!" seguida del nombre de un programa, bash emplea tal programa como intérprete del archivo. Como parámetros para el intérprete emplea los que estén en la primera línea del archivo, seguidos del nombre del archivo y a continuación otros parámetros que el usuario hubiera dado desde la línea de comandos.
- Si el archivo es tipo texto pero no comienza con #!, lo interpreta con el programa bash [1]. Es decir lo trata como un script para el intérprete de comandos.
- Si el archivo es binario lo envía al kernel para su ejecución. El kernel podrá ejecutarlo si está en un formato reconocido (e.g el ejecutable producido por un compilador en un formato reconocido por Linux
ELF, a.out).
Con estos caracteres comienza un archivo tipo texto que debe ser interpretado cuando el usuario solicita su ejecución, a continuación de ellos debe estar la ruta del intérprete.
Una variable es un nombre al cual se le puede asociar un valor, tal valor puede cambiar durante la ejecución de un programa
es 'variable'. Cada programa (incluyendo al intérprete de comandos) se inicia en un ambiente el cual consta de variables
variables de ambiente
que hereda del programa que lo inició y que pueden tener un significado especial para el programa. Las variables de ambiente que un programa usa se especifican en la página del manual del programa.
Palabras empleadas por bash y otros programas, que tienen asociado un valor. Algunos ejemplos son
PATH,
MAIL y
USER (su respuesta debe estar en minúsculas).
Para asignar un valor a una variable de ambiente y crearla si no existe, teclee el nombre de la variable, en seguida el carácter '=' y después el valor. El valor puede constar de letras, símbolos o números, pero tenga en cuenta que hay algunos caracteres con significado especial y que es mejor evitar en sus primeros experimentos: $, {, }, `, ' (podrá escribirlos precedidos de \ o encerrando el valor a asignar entre apostrofes). Por ejemplo para asignar el valor
/home a la variable
DIR:
DIR=/home
Estando en bash, cone esta orden puede asignar el valor
1 a la variable de ambiente
VAR.
Después de asignar una variable, puede emplear el valor asociado a la misma en comandos que de al intérprete de comandos, para hacerlo emplee el nombre de la variable precedido del carácter '$'. Por ejemplo
ls -l $DIR listará los archivos de la ruta asociada a la variable
DIR.
Para emplear el valor de una variable de ambiente en sus scripts para el intérprete de comandos, debe anteponer este caracter al nombre de la variable.
En bash puede emplear el comando
echo para enviar a salida estándar una cadena (por ejemplo
echo tarea > porhacer.txt dejar en el archivo
porhacer.txt una línea con la palabra
tarea), esto puede usarse para examinar el valor de una variable de ambiente, e.g.
echo $DIR presentará el valor de la variable
DIR.
Orden para el intérprete de comandos que le permitirá examinar el valor de la variable de ambiente
VAR.
Puede examinar las variables de ambiente de bash con el comando
set. Algunas de las variables que verá son:
USER y
USERNAME cuyo valor es el login del usuario;
UID con el número que identifica al usuario;
TERM mantiene el nombre de la terminal que está usando (ver
);
SHELL la ruta y nombre del intérprete de comandos;
PWD el nombre del directorio de trabajo;
$HOME el nombre del directorio personal del usuario;
PS1 y
PS2 indican a bash como presentar prompts (see
);
PATH es la ruta de directorios donde bash busca archivos ejecutables, se separan unas rutas de otras con el caracter ':';
OSTYPE el tipo de sistema operativo;
MAILCHECK la frecuencia en segundos con la que bash debe revisar si ha llegado un nuevo correo a la cola de correos especificada en la variable
MAIL (por defecto la del usuario);
LS_COLORS colores que emplea el programa
ls;
LINES y
COLUMNS indican la cantidad de filas y columnas de la terminal que está usando;
LANG,
LANGUAGE y otras variables que comienzan con el prefijo
LC_ especifican el idioma en el que los programas deben interactuar con el usuario (ver
);
HOSTNAME es el nombre del sistema;
HISTFILE mantiene el nombre del archivo con la historia de comandos, su tamaño lo limitan
HISTFILESIZE y
HISTSIZE;
DISPLAY mantiene la dirección del servidor X-Window (see
Lectura Servicios de la Intranet).
Nombre de la variable de ambiente que mantiene la dirección del servidor X-Window.
Cuando se inicia un programa desde bash, el ambiente que tendrá constará de las variables que estén marcadas como exportables y de otras variables que se especifiquen al comienzo del comando (pueden separarse unas de otras con espacios y si el valor de alguna variable debe tener espacios puede encerrar el valor completo entre comillas), por ejemplo para iniciar el programa
man en un ambiente con las variable
LANGUAGE y
LANG en el valor
DE_de:
LANG=de_DE LANGUAGE=de_DE man man
Orden que debe dar a bash para iniciar el programa
miprograma con un ambiente en el que la variable de ambiente
VAR tenga el valor 1.
Para exportar una variable y lograr así que forme parte del ambiente de procesos creados por su sesión, puede emplear bien
declare -x VAR o
export VAR, empleando el nombre de la variable que desea exportar en lugar de
VAR. Empleando sólo
export o sólo
declare -x puede ver los nombres y valores de variables exportables.
Orden que debe dar en un script para el intérprete de comandos, para exportar la variable VAR al ambiente del proceso que inicie el script.
En un script puede emplear ciertas variables especiales ($1, $2, ...) para referenciar los parámetros que el usuario empleó al iniciarlo. $1 tendrá el valor del primer paramétro, $2 del segundo y así sucesivamente. El siguiente script ejemplifica su uso:
#!/bin/bash
echo "Creando $2.tar.gz de $1"
mkdir $2
cp -rf $1/* $2
tar cvf $2.tar
gzip $2.tar
Este script recibe dos parámetros, el primero es una ruta y el segundo el nombre de un archivo. Si el nombre del script es
comp y tiene permiso de ejecución podría usarse para crear un paquete comprimido
d.tar.gz con el contenido del directorio
~/mand con:
./comp ~/mand d
Note que en el ejemplo indicamos la ruta completa del archivo
comp, suponiendo que es ejecutado desde el mismo directorio donde se encuentra. Si la ruta donde está el archivo está en la variable
PATH, no es necesario especificar la ruta.
En un script para el intérprete de comandos se usa para referenciar el primer parámetro que el usuario pase al ejecutarlo.
bash trata algunos caracteres de forma especial:
' " { } $. Al asignar una variable o iniciar un comando bash "expande" estos caracteres y su contexto de varias formas :
Referencia la cantidad de parámetros que un script para bash recibe.
Referencia todos los parámetros que un script para bash recibe.
Cuando la ejecución en primer plano de un comando termina, esta "variable" del intérprete de comandos referencia el número retornado, es 0 sólo si la operación fue exitosa.
Referencia las opciones que un usuario pasa a un script cuando lo ejecuta.
Referencia la identificación del proceso del intérprete de comandos desde el que se ejecuta un script.
Referencia la identificación del proceso del último comando ejecutado en segundo plano.
En un script, referencia el nombre de script o shell que el usuario emplea para ejecutarlo.
En una orden para bash, una cadena puede encerrarse entre dos caracteres como este, por ejemplo para incluir espacios. Al encerrarla entre caracteres como este, se realizan expansiones excepto expansión de corchetes y de nombres de archivos.
Secuencia que representa el caracter fin de línea en scripts para el intérprete de comandos.
Secuencia que indica borrar el caracter de la izquierda en scripts para el intérprete de comandos.
En el intérprete de comandos puede usarse esta secuencia para producir el caracter '$'.
En el intérprete de comandos puede usarse esta secuencia para producir el caracter tabulador.
En una orden para bash, una cadena puede encerrarse entre dos caracteres como este para evitar expansiones, por ejemplo para incluir espacios y símbolos reservados de bash como el caracter '$'.
En bash este caracter expande a todos los archivos de un directorio
o a * si no hay archivos en el directorio.
En bash expande al directorio del usuario.
Cadena que bash presenta, si en un directorio hay archivos con nombres: g1,g10,g3,grupo,texto y desde ese directorio se ejecuta la orden
echo g?
$var -
Expansión de variables o parámetros
El caracter '
$' es empleado para distinguir variables o bien parámetros de un script. Las variables son remplazadas por su valor, por ejemplo
echo $PATH presentará el contenido de la variable
PATH. En un script los parámetros se referencian con números,
$1 es el primero,
$2 el segundo y así sucesivamente. Otros nombre especiales en un script son:
$#
Es remplazado por la cantidad de parámetros que el script recibe.
$*
Que se expande a todos los parámetros que el script haya recibido, un parámetro se separa de otro con el valor de la variable
IFS que normalmente es un espacio.
$?
Todo programa al terminar debe retornar un número al sistema operativo, por convención 0 significa operacióne exitosa y números diferente representan errores.
$? se expande al número retornado por el último programa ejecutado en primer plano. Un script puede retornar un 3 en lugar de 0 con
exit 3
$-
Opciones que se pasaron al script durante su ejecución.
$$
Identificación del proceso del intérprete de comandos.
$!
Identificación del proceso del último comando que se ejecutó en segundo plano.
$0
Nombre del script o del shell.
"texto" -
citas
Cuando un conjunto de caracteres (incluyendo espacios), se encierra entre comillas, bash los trata como una sola cadena. Esto es útil por ejemplo cuando el nombre de un directorio o archivo tiene espacios, e.g.
cd "los amigos". Otra forma de representar el caracter espacio es con el caracter '
\' seguido de un espacio, así el efecto del ejemplo anterior también podría lograrse con
cd los\ amigos. Hay otros caractéres que pueden representarse con ayuda de '
\', por ejemplo:
Cadena que bash produce al ejecutar: echo a{a,e}
\n
Representa el caracter fin de línea.
\b
Caracter para borrar a la izquierda.
\\ \{ \} \$
Representan los caracteres '\' '{' '}' y '$' respectivamente. Esto es útil para producir estos caracteres sin que bash trate de interpretarlos --estos son caracteres para hacer expansiones.
\a
Caracter para emitir un sonido.
\t
Caracter tabulador (como la tecla
Tab).
{letras} -
expansión de corchetes
Una cadena que contenga
{ letra1, letra2, ... } será expandida a varias cadenas similares a la inicial pero la posición de
{letras1, letra2, ...} será remplazada por cada una de las letras. Por ejemplo
ls /home/juan/sal{a,e}n se expandirá a
ls /home/juan/salan /home/juan/salen. Esta expansión es la primera que se realiza cuando hay varias en un mismo comando, y sólo surge efecto si está fuera de comillas o apóstrofes.
`comando` o $(comando) - sustitución de comandos
Un comando encerrado entre apóstrofes invertidos (i.e `
comando`) o entre las cadenas "
$(" y "
)", será expandido al resultado que tal comando envíe a salida estándar cuando es ejecutado. Por ejemplo
TEXTOS=`ls *.txt`
asignará a la variable
TEXTOS los nombres de los documentos tipo texto (i.e el resultado de
ls *.txt).
ls $(cat rutas.txt)
presentará los archivos de los directorios que estén en el archivo
rutas.txt.
Que valor queda almacenado en la variable a tras ejecutar las siguientes ordenes en bash: echo "un ejemplo" > arch.tmp ; a=`cat arch.tmp`
'texto' -
citas
Un texto que se encierra entre apóstrofes no es expandido. Esto es útil cuando se requiere una cadena que tiene algunos caracteres reservados para expansiones. Por ejemplo
N=10
echo '$N' es $N
enviará a salida estándar
$N es 10
$((expresión)) -
expansión aritmética
Una expresión aritmética [2] será evaluada cuando se encierre entre
$(( y
)), por ejemplo:
echo "1+2 es $((1+2))"
Resultado produce la siguiente orden para bash: echo "2*2=$((2*2))"
*, ?, ~ [letras] [rango(s)]-
Expansión de rutas
Algunos caracteres y secuencias son expandidos a nombres de archivos. A continuación se presentan con ejemplos:
- echo *, presentará todos los nombres de archivos del directorio de trabajo
porque * expande a todos estos y echo los presenta
. En caso de que no haya archivos el caracter * no será expandido y será mostrado por echo.
- echo datos?.gnumeric se expandirá a todos los nombres de archivos que comiencen por datos seguidos de un caracter arbitrario a su vez seguido de la cadena .gnumeric.
- echo ~/.*errors presentará todos los nombres de archivos de configuración que estén en el directorio del usuario y que terminen con errors.
- rm *[cho] eliminará todos los archivos que terminen con una de las letras o, h o c.
- echo [0-9][a-z]* presentará todos los archivos que comiencen con un dígito seguido de una letra.
Cadena que bash presenta, si en un directorio hay archivos con nombres: g1,g10,g3,grupo,texto y desde ese directorio se ejecuta la orden
echo *[o3]
Cadena que bash presenta, si en un directorio hay archivos con nombres: g1,g10,g3,grupo,texto y desde ese directorio se ejecuta la orden
echo [a-z][a-z]*