Introducción a la programación de scripts bash/sh
Una de las cosas que más utilidad tienen en el mundo linux, es la programación de shelll scripts, dado que éstos nos dan la posibilidad de preparar tareas que simplifican nuestro trabajo diario.
Este árticulo intenta ser una breve introducción al mundo de la programación de scripts
Lo primero que necesiamos es un editor de texto, cualquiera, pero que guarde el archivo como text/plain
1. Creando un script
Vamos a crear un archivo, hola.sh. Para esto abrirmos nuestro editor favorito y escribimos el típico Hola Mundo
#!/bin/sh #este es un comentario echo Hola Mundo! |
Para ejecutarlo, podemos hacerlo pasando el nombre del archivo a la llamada de nuestra shell (bash, sh u otra), en este caso sh
$ sh hola.sh |
O podemos darle permisos de ejecución con el comando chmod
$ chmod +x hola.sh |
Una vez añadido el permiso de ejecución, ya podemos ejecutarlo directamente:
$ ./hola.sh |
Pero si queremos ejecutar nuestro nuevo script desde cualquier lugar, debemos guardarlo en algún directorio que este en nuestro PATH, como recomendación /usr/local/bin o /usr/bin (directorios donde se guardan los ejecutables)
Si observamos el código fuente de nuestro pequeño script, veremos que consta de tres líneas:
- En la primera se indica el shell que se va a usar como intérprete para este script: #!/bin/sh. Esta siempre debe ser la primera línea de un shell script. (puede ser /bin/bash u otro)
- La segunda contiene una liena que es un simple comentario (deben comenzar con #)
- La tercera línea contiene el comando echo, que muestra un mensaje por pantalla.
2. Variables
Una variable es un contenedor que almacena un valor. Utilizamos variables para guardar valores que necesitaremos en nuestro script. A diferencia de otros lenguajes de programación, en Shell las variables no tiene un tipado especifico.
Ejemplos: # Asignamos el valor 1 a i i=1 # Asignamos Bienvenidos a la programación de shell scripts! a la variable cadena cadena="Bienvenidos a la programación de shell scripts!" |
Importante: No podemos dejar espacios entre la variable y el igual o el igual y el valor, porque el shell lo interpretará como un comando y nos dará error.
Veamos ahora como podemos obtener el valor de una variable.
Para acceder al contenido de una variable empleamos $ delante de su identificador:
Ejemplos: $ i=4 # Mostramos el valor de la variable i por pantalla echo $i echo "El valor asignado a i es $i" |
3. Usando parámetros
También existe la posibilidad de usar parametros en nuestros scripts, estos parámetros son valores externos al programa que son pasados desde la linea de comandos.
$0 contiene el nombre nombre de nuestro script
$# contiene el número de parámetros con los que se ha invocado al shell
$n contiene los parámetros, con n de 1 a 9 (a $#)
{$n} cuando n > 9, tenemos qu especificar los parámetros entre llaves
$$ contiene el PID de nuestro proceso
$* todos los parámetros menos $0
|
4. La salida de los programas
Cuando se ejecuta un programa, un comando UNIX es un programa, podemos, a parte de redirigir su entrada y su salida, recoger el resultado de su ejecución y su salida.
El resultado es un valor numérico, por lo general cero si todo ha ido bien, y distinto de cero si ha habido alguna clase de error.
- Para obtener el resultado de la ejecución del último comando, utilizamos $?
Ejemplo: mkdir /home/alumnos/$idalumno > /dev/null ; echo $? if [ $?=0 ]; then echo "El directorio $idalumno se ha creado sin problemas" fi |
- Para obtener la salida de un comando, utilizamos $(comando) o comillas invertidas: `comando`
Ejemplo: $ directorioactual=`pwd` $ echo $directorioactual |
- Para devolver el resultado de ejecución de un script, utilizamos exit valor, donde valor debe ser un numéro entero.
Ejemplo: exit 0 # Termina el programa y devuelve cero como valor de salida |
5. Operadores aritméticos
Si queremos que el shell evalúe una operación aritmética y no la tome como argumentos de un comando, escribiremos la expresión observando la siguiente sintaxis: $((expresion))
Al escribir la expresión de este modo, el shell la evalúa y la reemplaza por su valor.
Ejemplo: $ echo $((1+1)) |
Algunos de los operadores aritméticos soportados son:
+ la suma * la mutiplicación - la resta / la división entera % el resto de la división entera ( ) los paréntesis nos sirven para agrupar operaciones |
6. Operadores de comparación
Podemos hacer comprobaciones sobre ficheros utilizando el comando test.
El comando test evalúa una expresión y retorna un valor que será cero si la expresión es verdadera o distinto de cero si la expresión es falsa.
Este comando tiene la siguiente sintaxis:
test expresion [ expresion ] |
donde EXPRESION puede ser una evaluación: de cadenas de caracteres, números enteros, archivos (evaluamos permisos y existencia del archivo) u operadores lógicos que permiten realizar una combinación de varias evaluaciones.
- Utilización abreviada del comando test.En vez de escribir test EXPRESION, podemos escribir la EXPRESION entre corchetes( [ ] ) y el resultado será exactamente el mismo.
Ejemplo: $ str="abc" $ [ "$str" = "abc" ] $ echo $? |
Habitualmente el comando test se utiliza en conjunto con la sentencia if para evaluar distintos tipos de expresiones que veremos a continuación.
6.1. Operadores sobre ficheros
-d fichero cierto si fichero existe y es un directorio -e fichero cierto si fichero existe, independientemente del tipo que sea -f fichero cierto si fichero existe y es un fichero normal -r fichero cierto si fichero existe y se puede leer -s fichero cierto si fichero existe y tiene tamaño mayor que cero -w fichero cierto si fichero existe y es se puede escribir sobre él -x fichero cierto si fichero existe y es ejecutable |
6.2. Operadores lógicos
! expresion cierto si expresion es falsa (negación) expresion1 -a expresion2 cierto si expresion1 y expresion2 son ciertas expresion1 -o expresion2 cierto si expresion1 o expresion2 son ciertas |
6.3. Operadores de comparación de números enteros
n1 -eq n2 cierto si los enteros n1 y n2 son iguales n1 -ne n2 cierto si los enteros n1 y n2 no son iguales n1 -gt n2 cierto si el enteros n1 es mayor que n2 n1 -ge n2 cierto si los enteros n1 y n2 son iguales o n1 es mayor que n2 n1 -lt n2 cierto si el enteros n1 es menor que n2 n1 -le n2 cierto si los enteros n1 y n2 son iguales o n1 es menor que n2 |
6.4. Operadores de comparación de cadenas
s1 = s2 cierto si las cadenas de texto s1 y s2 son idénticas s1 != s2 cierto si las cadenas de texto s1 y s2 no son idénticas s1 <> s2 cierto si la cadena de texto s1 es mayor que s2 -n cadena cierto si la longitud de la cadena de texto es distinta de cero |
6.5. Operadores lógicos && y ||
Además de los anteriores, existen los operadores lógicos && (AND, multiplicación lógica) y || (OR, suma lógica), que se puede aplicar al valor de salida de los programas:
$ true && true ; echo $? $ true && false ; echo $? $ false && true ; echo $? $ false && false ; echo $? $ true || true ; echo $? $ true || false ; echo $? $ false || true ; echo $? $ false || false ; echo $? |
7. Sentencias de comparación
7.1. Sentencia if
La forma más simple tiene la siguiente sintaxis:
if CONDICION; then bloque de comandos fi |
En este primer caso el bloque de comandos se ejecutará solo si la condición es evaluada a cierto.
Una segunda posibilidad es utilizar else:
if CONDICION; then bloque de comandos b1 else bloque de comandos b2 fi |
Ejemplo: read numero # comparamos cadenas de texto, así que usamos comillas if [ $numero -eq 5 ]; then echo Acerté tu número. Es el 5. fi |
7.2. Sentencia case
Se utiliza cuando el valor de una variable ha de ser contrastado con varios valores. Su sintaxis es la siguiente:
case variable in patron1) comando1 comando2;; patron2) comando3 comando4;; .... .... esac |
Comprueba si variable coincide con algunos de los patrones (patron1, patron2,…) y ejecuta los comandos asociados con la primera coincidencia que tiene lugar.
Sólo se ejecuta un único grupo de comandos.
El ";;" es el delimitador de los comandos que se ejecutaran para un determinado patrón y “esac" es el fin de la sentencia case.
Un ejemplo clásico de uso de la sentencia case es la creación de un menú:
8. Bucles
8.1. El bucle for
for VARIABLE in SERIE; do bloque de comandos done |
Podemos especificar los valores de la serie de dos formas:
- Nombrando todos los elementos de la serie:for i in 1 2 3 4 5; do
- Utilizando la sentencia seq:for i in seq 1 5; do
Ejemplos: for i in 1 2 3 4 5; do echo $i done for i in seq 1 5; do echo $i done # con cadenas de texto for palabra in uno dos tres cuatro cinco; do echo $palabra done |
8.2. El bucle while
while CONDICION; do bloque de comandos done |
Cada iteración se evalua la condición y en el momento que no sea cierta, el bucle termina.
# equivalente a seq 1 5 i=1 while [ $i -le 10 ]; do echo $i i=$(($i+1)) done # leemos de stdin hasta que se introduzca la palabra 'salir' read linea while [ $linea != "salir" ]; do read linea done |
8.3. Rompiendo la ejecución del bucle: break
for elemento in *; do echo Primer elemento $elemento break echo Esto nunca se llega a ejecutar done echo Seguimos con el programa |
9. Funciones
Veamos cuál es la sintaxis de una función:
nombre_funcion()
{
comando1
comando2
...
...
}
|
Luego, para ejecutar la función debemos llamarla por su nombre, igual que un comando:
... nombre_funcion ... |
Eso sí, debemos tener en cuenta que es necesario definir cada función antes de utilizarla. Veamos un ejemplo:
#!/bin/sh
mostrar_menu ()
{
echo -e "\n"
echo "[1] Crear usuario"
echo -e "[2] Salir\n"
read -p "Elija una opción: " OPCION
}
crear_usuario ()
{
if [ id | grep uid=0 ]; then
read -p "Nombre del usuario a crear: " NOMBREUSUARIO
useradd $NOMBREUSUARIO
else
echo '*****************************'
echo "Se necesitan permisos de root"
echo '*****************************'
fi
}
############# Programa principal #################
while true; do
mostrar_menu
case $OPCION in
1) crear_usuario ;;
2) echo "Abandonando el programa..."
break;;
*) echo '********************************************'
echo "Opción ingresada no valida, intente de nuevo"
echo '********************************************';;
esac
done
|
Saludos!!
PD: este post es una vil copia de un texto encontrado aquí







Se dice en…