Bash Shell PDF
Bash Shell PDF
BASH Shell
Objetivo
Presentar las principales características del interprete Bash
Shell y familiarizar al alumno con su uso.
2
¿Que es Bash Shell ?
Cada sistema operativo tiene su propio shell (e.g. Windows command promt)
cuya función principal es el interpretar las órdenes del sistema operativo
Bash (Bourne again shell) es un programa escrito para el proyecto GNU y está
basado en el shell de Unix. Es compatible con POSIX (IEEE POSIX
P1003.2/ISO 9945.2).
3
Programas compilados vs Scripting
Bash es no sólo un eficiente interprete de línea de instrucciones, sino también un
poderoso lenguaje scripting. El cual nos permite automatizar tareas que de otra
manera deberían realizarse de manera manual en la línea de comandos.
- Los lenguajes de programación son en general más poderosos y más veloces que los
lenguajes interpretados o scripting. Su código fuente es compilado tomando en
consideración la arquitectura del CPU, lo que genera un archivo ejecutable. Su
principal desventaja es que dichos ejecutables no pueden ser portados en otros
arquitecturas o incluso en otros sistemas operativos.
Antes de ejecutarlo hay que habilitar los permisos de ejecución del archivo:
$ ls -la Hola.sh
-rw-r--r-- Hola.sh
$ chmod 700 Hola.sh
$ ls -la Hola.sh
-rwx------ Hola.sh
$ ./Hola.sh
Hola Mundo
Para los archivos scripts utilizamos la extensión .sh para poderlos identificar de otro
tipo de archivos
Variables
Las Variables son almacenados como tipo cadena de texto «Strings»
#!/bin/bash
El valor de la variable se
STR=“Hola Mundo”
recupera anteponiendo un
echo $STR símbolo ‘$’ a su nombre
Nota: \ es el carácter ascii de bash usado para preservar el valor literal del
siguiente carácter en la cadena « \ : escape character»
$ ls \*
ls: * : No such file or directory
Comillas simples y dobles
Cuando se asignan cadenas de caracteres que contengan espacios en blanco o caracteres
especiales, se acostumbra encerrar la cadena entre comillas simples (apostrofes) o comillas
dobles
Las comillas dobles harán que si, dentro de su contenido se referencia una variable (e.g.
$var), ésta sea resuelta a su valor
$ var=“test string”
$ new_var=“Value of var is $var”
$ echo $new_var
Value of var is test string
Las comillas sencillas (apóstrofes) por el contrario harán que las variables (e.g. $var) NO
resuelvan su valor como parte de la cadena.
$ var=’test string’
$ new_var=’Value of var is $var’
$ echo $new_var
Value of var is $var
Si el proceso hijo modifica el valor de la variable x, esta no modificará el valor original del
proceso padre:
$ x=adios
$ exit
$ echo $x
hola
Variables de Ambiente
Hay dos tipos de variables de entorno:
– Variables locales
– Variables de Ambiente, también llamadas variables de entorno
Las Variables de Ambiente se establecen por el sistema « $ export foo=Hola ». y se pueden
listar utilizando la instrucción « env ».
Dentro de las Variables de Ambiente contienen valores especiales. Por ejemplo:
$ echo $SHELL
/bin/bash
$ echo $HOME # argumento por defecto (directorio home) del comando «cd»
/home/jjcg
El arranque del shell es más complejo; por ejemplo, si bash es usado de manera interactiva,
entonces /etc/bashrc o ~/.bashrc son leídos (Ver la documentación).
Variables de Ambiente (cont.)
PATH: el path de búsqueda de comandos.
– Es una lista de directorios, separados por «:», en donde se busca cualquier comando.
$ echo $PATH
/usr/X11R6/bin:/usr/local/bin:/bin:/usr/bin
Pero estableciendo la variable PATH=$PATH:. se incluye el actual (.) directorio de trabajo dentro
del propio PATH y por la tanto podremos ejecutar el script como cualquier otra instrucción del
shell:
$ my_script.sh # sin el ./
De manera más ordenada, si creamos el directorio ~/bin ($ mkdir ~/bin) y editamos el archivo
~/.bash_profile incluyendo las siguientes lineas:
PATH=$PATH:$HOME/bin
export PATH
#!/bin/bash #!/bin/bash
INSTRUCCIÓN_1 INSTRUCCIÓN_1
. . . . . .
exit 3
# sale con el estado de la ejecución
# de la última instrucción. # sale con el estado de la ejecución
ULTIMA_INSTRUCCIÓN # de la última instrucción.
ULTIMA_INSTRUCCIÓN
exit
exit 0
Command Substitution
El símbolo de acento invertido «`» lo utiliza la sintaxis del shell como modificador de contexto. Su efecto
es la de transferir la salida de la instrucción al ambiente del shell. En estos casos en lugar de
considerarse la cadena de caracteres ahí contenidos se tomará en cambio el resultado de la ejecución de
dicha cadena. (e.g.: var=`instrucción`)
$ LISTA=`ls`
$ echo $LISTA
hola.sh leer.sh
Opciones
– read -s (no hace echo de la entrada)
– read -nN (acepta sólo N caracteres de entrada)
– read -p “mensaje” (muestra un mensaje)
– read -tT (acepta una entrada por un tiempo máximo de T segundos)
Ejemplo
$ read -s -n1 -p "si (S) o no (N)?" respuesta
si (S) o no (N) ? N
$ echo $respuesta
N
Manipulación de strings
Varias opciones para manipular strings están disponibles en bash
${#string} regresa la longitud del string
${string:position} regresa el segmento de la cadena (string) desde la
posición marcada por $position
${string:position:length} regresa $length elementos de la cadena (string)
desde la posición marcada por $position
Ejemplos:
$ variable=0123456789
$ echo ${#variable}
10
$ echo ${variable:6}
6789
$ echo ${variable:6:2}
67
Verificación de variables
Para verificar si una variable está definida se puede usar:
${parameter?msg}
Si el parámetro ($parameter) existe, se envía a la salida
de lo contrario se imprime el mensaje msg
$ unset valor
$ unset total
$ valor=${total?'total no está definido'}
total: total no está definido
$ echo $valor
$ total=10
$ valor=${total?'total no está definido'}
$ echo $valor
10
Operadores aritméticos
+ suma
- resta
* multiplicación
/ división
** exponente
% módulo
Ejemplos:
$ a=(5+2)*3
$ echo $a
$ b=2**3
$ echo $a+$b
Evaluación aritmética
Con la instrucción « let » se puede utilizar para realizar funciones matemáticas:
$ let X=10+2*5
$ echo $X No es necesario utilizar $X
20 para referenciar el valor de X
$ let Y=X+2*4
$ echo $Y
28
Un expresión aritmética se puede evaluar con $[expresión] o $((expresión))
$ echo $((123+20))
143
$ VALOR=$[123+20]
$ echo $[50*$VALOR]
7150
$ echo $[2**3]
8
$ echo $[8%3]
2
Evaluación aritmética (cont.)
Ejemplo (operaciones.sh)
#!/bin/bash
echo -n “Introduzca un primer número: ”; read x
echo -n “Introduzca un segundo número : ”; read y
suma=$(($x + $y))
resta=$(($x - $y))
mul=$(($x * $y))
div=$(($x / $y))
mod=$(($x % $y))
if [ expresión ];
then
instrucciones
elif [ expresión ];
then
instrucciones
else
instrucciones
fi
Ejemplos:
[ s1 = s2 ] (verdadero si s1 es igual a s2)
[ s1 != s2 ] (verdadero si s1 es diferente a s2)
[ s1 ] (verdadero si s1 no está vacía)
[ -n s1 ] (verdadero si s1 tiene longitud mayor que 0)
[ -z s2 ] (verdadero si s2 tiene longitud igual a 0)
Expresiones (cont.)
Comparación numérica con [ ] :
-eq evalúa si dos números son iguales
-ne evalúa si dos números son diferentes
Ejemplos:
[ n1 -eq n2 ] (verdadero si n1 es igual a n2 )
[ n1 -ne n2 ] (verdadero si n1 es diferente a n2 )
[ n1 -ge n2 ] (verdadero si n1 es mayor o igual a n2 )
[ n1 -le n2 ] (verdadero si n1 es menor o igual a n2 )
[ n1 -gt n2 ] (verdadero si n1 es mayor que n2 )
[ n1 -lt n2 ] (verdadero si n1 es menor que n2 )
Ejemplos $ cat > comparacion2.sh
#!/bin/bash
echo -n “Introduzca un número entre 1 y 10: "
$ cat > comparacion1.sh read num
#!/bin/bash if [ “$num” -lt 10 ]; then
if [ “$num” -gt 1 ]; then
echo -n “Introduzca su nombre de usuario: "
echo “$num*$num=$(($num*$num))”
read login
fi
if [ “$login” = “$USER” ]; then else
echo “Hola, $login. Cómo está hoy?” echo “Número fuera del intervalo!”
else fi
echo “Tú no eres $login!!!” echo -n "Introduzca otro número entre 1 y 10: "
fi read num
if (( $num <= 10 )); then
if (( $num >= 1 )); then
echo "$num**$num=$(($num**$num))"
fi
else
echo "Número fuera del intervalo!"
fi
Expresiones (cont.)
Operadores de archivos:
-d evalúa si el path dado es un directorio
-f evalúa si el path dado es un archivo
-e evalúa si el archivo existe
-s evalúa si el archivo tiene un tamaño mayor a 0 bytes
-r evalúa si el archivo tiene permiso de lectura
-w evalúa si el archivo tiene permiso de escritura
-x evalúa si el archivo tiene permiso de ejecución
Ejemplos:
[ -d cadena_de_caracteres ] (verdadero si la cadena corresponde a un directorio)
[ -f cadena_de_caracteres ] (verdadero si la cadena corresponde a un archivo )
[ -e cadena_de_caracteres ] (verdadero si existe )
[ -s cadena_de_caracteres ] (verdadero si el archivo tiene datos )
[ -r cadena_de_caracteres ] (verdadero si el archivo tiene permiso de lectura )
[ -w cadena_de_caracteres ] (verdadero si el archivo tiene permiso de escritura )
[ -x cadena_de_caracteres ] (verdadero si el archivo tiene permiso de ejecución )
Ejemplos: operadores de archivos
$ cat > comparacion3.sh $ cat > comparacion4.sh
#!/bin/bash #!/bin/bash
echo -n “Introduzca el nombre de un archivo: " if [[ $1 = “directory” ]]; then
read file_name find /etc -maxdepth 1 -type d
# if [ -f /etc/fstab ]; then elif [[ $1 = “link” ]]; then
if [ -f $file_name ]; then find /etc -maxdepth 1 -type l
cp $file_name . elif [[ $1 = “file” ]]; then
echo “Archivo $file_name copiado” find /etc -maxdepth 1 -type f
else else
echo “El archivo $file_name no existe !!!” echo "Usage: $0 file | directory | link "
exit 1 fi
fi
Nota: El uso reiterado de elif resulta en una ejecución ineficiente. Para casos donde se
requiera la verificación reiterada de un valor se favorece el uso del condicional case.
Operadores lógicos
! negación (NOT) seguida de la expresión lógica
-a operación AND entre dos expresiones lógicas
-o operación OR entre dos expresiones lógicas
Cada grupo de evaluación de expresiones e instrucciones relacionadas debe separarse con punto y
coma dobles « ; ; ».
$ cat > case.sh
case $var in #!/bin/bash
val_1 ) case $1 in
instrucciones ;; “directory”)
val_2)
find /etc -maxdepth 1 -type d ;;
instrucciones ;;
“link”)
val_n)
find /etc -maxdepth 1 -type l ;;
instrucciones ;;
“file”)
*)
find /etc -maxdepth 1 -type f ;;
instrucciones ;;
esac *)
echo "Usage: $0 file | directory | link " ;;
esac
El *) usado para aceptar cualquier otra
condición no listada en las anteriores opciones
Estructuras tipo while
Las estructuras tipo « while » son estructuras de repetición cíclica usadas para
ejecutar un conjunto de instrucciones de manera reiterada tanto la condición
definida sea verdadera.
$ cat for_loop4.sh
#!/bin/bash
echo –n “Introduzca un número: ”; read x
let suma=0
for (( i=1 ; $i<$x ; i=$i+1 )) ; do
let “suma = $suma + $i”
done
echo “La suma de los primeros $x números es: $suma”
Operador continue
El operador continue produce un salto a la siguiente iteración cuando se
encuentra dentro de la ejecución de un ciclo, evitándose la ejecución de las
subsiguientes instrucciones dentro del lazo.
$ cat continue.sh
#!/bin/bash
LIMIT=19
echo
echo “Imprimir los números del 1 al 20 (excepto 3 y 11)”
a=0
while [ $a -le “$LIMIT” ]; do
a=$(($a+1))
if [ “$a” -eq 3 ] || [ “$a” -eq 11 ]
then
continue
fi
echo -n “$a ”
done
Operador break
El operador break, cuando se ejecuta, termina con las iteraciones del ciclo.
Simplemente lo rompe.
$ cat break.sh
#!/bin/bash
LIMIT=19
echo
echo “Imprimir los números del 1 al 20 ( pero al llegar al 2 ... )”
a=0
while [ $a -le “$LIMIT” ]; do
a=$(($a+1))
if [ “$a” -gt 2 ]
then
break
fi
echo -n “$a ”
done
Arreglos (listas)
En bash se pueden definir arreglos. La forma más simple de hacerlo es
mediante: transporte=(automovil avion barco bicibleta) o de manera
explícita:
oficio[0]=carpintero
oficio[1]=ingeniero
oficio[2]=plomero
$ nano depurar.sh
#!/bin/bash -x
echo -n “Introduzca un número: ”; read x
let sum=0
for (( i=1 ; $i<$x ; i=$i+1 )) ; do
let “sum = $sum + $i”
done
echo “La suma de los $x primeros números es: $sum”
Depuración
Ejemplo -x Ejemplo -v
$ ./depurar.sh $ ./depurar.sh
+ echo -n 'Introduzca un número: ' #!/bin/bash -v
Introduzca un número: + read x echo -n "Introduzca un número: "; read x
3 Introduzca un número: 3
+ let sum=0 let sum=0
+ (( i=1 )) for (( i=1 ; $i<$x ; i=$i+1 )) ; do
+ (( 1<3 )) let "sum = $sum + $i"
+ let 'sum = 0 + 1' done
+ (( i=1+1 )) echo "La suma de los $x primeros números es:$sum"
+ (( 2<3 )) La suma de los 3 primeros números es: 3
+ let 'sum = 1 + 2' $
+ (( i=2+1 ))
+ (( 3<3 ))
+ echo 'La suma de los 3 primeros números es: 3'
La suma de los 3 primeros números es: 3
$
Ejemplo: grep + nano
$ nano grepedit.sh
#!/bin/bash
# Si los archivos listados en los parámetros $2 en adelante incluyen
# la cadena de caracteres (pattern) del argumento $1 serán abiertos con “nano”
if [ $# -le 1 ]
then
echo "Usage: $0 pattern file1 …" ; exit 1
else
pattern=$1 # Guardar el parámetro $1 original en “pattern”
shift # Correr un lugar hacia la izquierda el resto de parámetros
while [ $# -gt 0 ]; # El nuevo $1 contiene ahora el primer nombre de archivo
do
grep "$pattern" $1 > /dev/null
if [ $? -eq 0 ] ; then # Si grep encuentra una coincidencia
nano $1 # el archivo es abierto con el editor nano
fi
shift
done
fi
echo “La suma de los $x primeros números es: $sum”
Funciones
En bash se pueden definir funciones usando sólo el nombre de la función [ e.g. Nombre( ) ] o
usando la instrucción « function »
$ nano funcion.sh
#!/bin/bash
hello()
{
echo "You are in function hello()"
}
function Hola()
{
echo "Ahora está dentro de la función Hola()"
}
echo "Calling function hello()…"
hello
echo "You are now out of function hello()"
echo
echo "Llamando a la función Hola()…"
Hola
echo "Ahora está afuera de la función Hola()"
Funciones (cont.)
Ejemplo
$ nano funcion.sh
#!/bin/bash
function check() {
if [ -e "/home/$1" ]
then
return 0
else
return 1
fi
}
echo “Introduzca el nombre del archivo: ” ; read x
if check $x
then
echo “$x existe !”
else
echo “$x no existe !”
fi
Ejemplo Script1.sh
Selección de una carta aleatoria de una baraja de cartas
$ nano script1.sh
#!/bin/bash
# Paso I : Listar los elementos
Palo=“Bastos Diamantes Corazones Espadas”
Denominaciones=“2 3 4 5 6 7 8 9 10 Joto Qüina Rey Ás”
$ nano script1.sh
#!/bin/bash
# Paso I : Recorrer todos los archivos en el directorio
for filename in *
do
# Obtener el nombre del archivo sin path.
fname=`basename $filename`