Você está na página 1de 33

UNIVERSIDAD NACIONAL AUTÓNOMA DE MÉXICO

FACULTAD DE CONTADURÍA Y ADMINISTRACIÓN

LICENCIATURA EN INFORMÁTICA

SISTEMAS OPERATIVOS MULTIUSUARIOS

GONZÁLEZ GUIZAR GRISELDA SOCORRO

“ESTRUCTURAS DE CONTROL EN SHELL”

ZAMORANO PARTIDA RAINIER

2291

ABRIL 2011, MÉXICO D.F.

1
ÍNDICE

CARÁTULA-------------------------------------------------------------------------------------------------1
INTRODUCIÓN--------------------------------------------------------------------------------------------3
CONTENIDO-----------------------------------------------------------------------------------------------5
Programación Shell en Linux
¿Qué es Shell?
Shells disponibles en Linux
Principios de los Shell, Operación de los Shells y conceptos básicos de sintaxis--------------6
Estructuras de Control------------------------------------------------------------------------------------7
Secuencias Condicionales : IF ... FI
Control de Flujo------------------------------------------------------------------------------------------8
Estructura CASE
Lazos FOR----------------------------------------------------------------------------------------9
Bucle WHILE-------------------------------------------------------------------------------------10
Bucle UNTIL
BREAK & CONTINUE
Ciclos de Control
El ciclo While-----------------------------------------------------------------------------------11
El ciclo For--------------------------------------------------------------------------------------13
Control de Ciclos----------------------------------------------------------------------------------------14
Secuencia Condicional CASE … ESAC----------------------------------------------------------15
Bucles FOR--------------------------------------------------------------------------------------17
Bucles WHILE-----------------------------------------------------------------------------------19
Sintaxis De Las Sentencias De Control------------------------------------------------------------------20
CASE ... IN ... ESAC
IF ... THEN ... FI----------------------------------------------------------------------------------21
FOR ... DO ... DONE-----------------------------------------------------------------------------22
WHILE ... DONE---------------------------------------------------------------------------------23
UNTIL ... DONE
Estructuras Condicionales y Selectivas------------------------------------------------------------------24
Estructuras Condicionales
Estructura Selectiva-----------------------------------------------------------------------------26
Bucles----------------------------------------------------------------------------------------------------28
Bucles Genéricos
Bucles Condicionales While & Until------------------------------------------------------------30
Bucle de Selección Interactiva------------------------------------------------------------------31
CONCLUSIONES-----------------------------------------------------------------------------------------32
BIBLIOGRAFÍA--------------------------------------------------------------------------------------------33
MESOGRAFÍA

2
INTRODUCCIÓN

El intérprete de mandatos o "shell" es la interfaz principal entre el usuario y el


sistema, permitiéndole a aquél interactuar con los recursos de éste. El usuario
introduce sus órdenes, el intérprete las procesa y genera la salida correspondiente.
Por lo tanto, un intérprete de mandatos de Unix es tanto una interfaz de ejecución
de órdenes y utilidades, como un lenguaje de programación, que admite crear
nuevas órdenes –denominadas guiones o “shellscripts”–, utilizando combinaciones
de mandatos y estructuras lógicas de control, que cuentan con características
similares a las del sistema y que permiten que los usuarios y grupos de la máquina
cuenten con un entorno personalizado.
En Unix existen 2 familias principales de intérpretes de mandatos: los basados en el
intérprete de Bourne (BSH, KSH o BASH) y los basados en el intérprete C (CSH o
TCSH).

No es un secreto que los sistemas operativos Unix/Linux han evolucionado en los


últimos años como un sistema operativo popular. Para los programadores que han
utilizado Unix/Linux por muchos años, esto no es una sorpresa: Los sistemas
Unix/Linux proveen una plataforma eficiente y elegante para el desarrollo de
sistemas. Después de todo, esto es lo que Dennis Ritchie y Ken Thompson
buscaban cuando ellos desarrollaron Unix en los laboratorios Bell (a finales de los
60's).
Una de las características fuertes de los sistemas Unix/Linux es su gran colección de
programas. Más de 200 comandos básicos que se incluyen con el sistema
operativo. Estos comandos, (también conocidos como herramientas) hacen
prácticamente todo, desde contar el número de lineas en un archivo, enviar correo
electrónico, desplegar un calendario del año deseado, etc.
Pero la real fortaleza de los sistemas Unix viene no precisamente de esta gran
colección de comandos, sino también de la elegancia y facilidad con que estos
comandos pueden ser combinados para realizar funciones más sofisticadas.
Con el fin de proveer una interface consistente y fácil para que el usuario
interactuara con el sistema Unix/Linux (el kernel) se desarrolló el shell.
El shell es simplemente un programa que lee los comandos que se teclean y los
convierte en una forma más entendible para el sistema Unix/Linux. También incluye
algunas sentencias básicas de programación que permiten: tomar decisiones,
realizar ciclos y almacenar valores en variables.

3
El shell estándar distribuido con Unix y Linux, se deriva de la distribución de AT&T,
el cual a su vez, evoluciono de una versión originalmente escrita por Stephen
Bourne en los laboratorios Bell. Desde entonces la IEEE ha creado estándares
basados en el Bourne Shell y otros shells más recientes. La versión actual de este
estándar es "The Shell and Utilities Volume of IEEE Std 1003.1-2001", también
conocido como es estándar POSIX (Portable Operating System Unix)
Debido a que el shell ofrece un lenguaje de programación interpretado, se pueden
escribir, modificar y verificar programas rápidamente y de forma fácil.
La programación en shell es una parte fundamental de la administración de
sistemas basados en Unix, debido a la facilidad y poderío que el conjunto de
herramientas y comandos de Unix proveen para realizar la automatización de
procesos rutinarios, tales como: respaldo de archivos, captura de datos, verificación
de procesos, etc.

4
CONTENIDO

Programación Shell en Linux


El turno ahora es para los intérpretes de comandos de Linux y su programación,
conocida como programación shell. Aunque el intérprete de comandos es
independiente del lenguaje de programación utilizado, Linux permite crear
programas utilizando características propias de cada uno de los shell existentes.
¿cómo, no hay solo un intérprete? No; hay bastantes shells para Linux (o
intérpretes de comandos o consolas o como lo llames [de ahora en adelante shell]).
No como en Windows que tan solo tiene el intérprete de DOS (o cmd o command).
Como habrás podido deducir la programación en shell es “interpretada”, no
compilada, lo que reduce el desempeño del sistema; pero la ventaja es la facilidad
de creación y mantención.

¿Qué es Shell?
Unos dicen que es el sistema operativo, otros dicen que es una pantalla negra sin
sentido y anticuada, otros dicen que es la causa de que Linux no sea famosa entre
gente inexperta. ¿quién tiene la razón? Hagan sus apuestas!!! No, ahora en serio.
NO es el sistema operativo (el sistema operativo es el software que dirige la
computadora, habla con el hardware, carga y ejecuta programas, etc.); cuando se
ve el indicador de la computadora y se escriben comandos para ejecutar, con lo
que estamos tratando es con el shell.
Una característica interesante de Linux, es que los shells son completamente
independientes. Como usuario tenemos la libertad de elegir entre uno u otro shell.
También es posible interactuar con un shell, y escribir comandos para otro.

Shells disponibles en Linux


Piensa que el shell es un programa que está entre el usuario y el sistema operativo.
Este programa interpreta lo que el usuario le indica (en su lenguaje) para manipular
el sistema operativo.
El shell original disponible en los sistemas UNIX era el shell Bourne (“sh”). Después
dos shells que se volvieron populares fueron shell Korn (“ksh”) y el el shell C (“csh”),
cada uno con sus características propias, ventajas y desventajas.
Los shells Bourne y el C fueron reescritos, como resultado ahora tenemos el
“Bourne again shell (Shell Bourne nuevamente)” o “bash”, y el shell T (“tcsh”). Los
tres shells están disponibles en casi todas las distros de Linux. Bash es
probablemente el shell más utilizado actualmente, y es el que viene por defecto en
la mayoría de las distros.

5
Principios de los Shell, Operación de los Shells y conceptos básicos de sintaxis

El shell es un programa que nos permite interactuar con el sistema operativo. La


“línea de comandos” es la entrada del usuario para el shell. El shell examina la línea
de comandos, verifica que lo que se ha escrito es correcto, determina si se ha
digitado el nombre de un programa (un programa binario o compilado), y de ser
así envía dicho programa al núcleo (kernel) para su ejecución.

Todos los comandos shell utilizan el siguiente formato:


comando opcion1 opcion2 opcion3 ... opcionN argumento1 argumento2 ...
argumentoN

Esta línea se conoce como línea de comandos; que consiste en un comando y una
o más opciones (y/o argumentos). Por lo general el espacio en blanco se ignora. En
Linux los comandos son sensibles al uso de mayúsculas y minúsculas, cosa que no
pasa en Windows. El comando se termina pulsando la tecla Enter; aunque se puede
continuar el comando en una nueva línea usando backslash (\).

Comando larguisisisisisisisimo opcion1 opcion2 opcion3 ... opcionN \ argumento1


argumento2 ... argumentoN

Además es posible concatenar varios comandos, separándolos con punto y coma


(;), por ejemplo:
clear; pwd; ls

6
Estructuras de Control

Secuencias Condicionales : IF ... FI

La sintaxis de ésta sentencia es :


if <condicion>
then
..... comandos ....
else
..... comandos ....
Fi

(la cláusula "else" puede omitirse ; sólo se usará cuando se requiera).

La condición puede escribirse como "test <argumentos>" o con corchetes. Es


imprescindible en
este último caso , poner espacios entre los corchetes y los valores.

Posibles condiciones y su sintaxis :

if [ <variable> = <valor> ] : variable es igual a valor. Ojo con los espacios en „=„ .
if [ <variable> != <valor> ] : variable es distinta a valor.
if [ <variable -eq <valor> ] : variable es igual a valor . La variable debe contener
números. En éste caso , valen las comparaciones siguientes :

-eq : Igual (equal)


-ne : Distinto (not equal)
-ge : Mayor ó igual (Greater or equal).
-le : Menor ó igual (Less or equal).
-lt : Menor que (Less than).
-gt : Mayor que (Greater than).
if [ -f <fichero> ] : Existe <fichero>. Ojo con los espacios.
if [ -d <fichero> ] : Existe <fichero> y es un directorio.
if [ -s <fichero> ] :Existe <fichero> y tiene un tamaño mayor de cero.
if [ -x <fichero> ] : Existe <fichero> y es ejecutable.

7
En el campo <condición> vale escribir comandos, los cuales se ejecutarán y el valor
de la
condición dependerá de dos factores :

* Retorno 0 del comando = VERDADERO.


* Retorno != 0 del comando = FALSO.

Ejemplo de ésto último sería el siguiente programa :

if grep jose /etc/passwd


then # retorno del comando -grep- ha sido CERO
echo "Jose esta registrado como usuario"
else # retorno del comando grep NO ha sido CERO.
echo "Jose NO esta registrado como usuario"
fi

Control de Flujo

Además del if bash permite otras estructuras de control de


flujo: case, for, while y until

Estructura CASE

case valor in
patrón_1)
comandos si value = patrón_1
comandos si value = patrón_1 ;;
patrón_2)
comandos si value = patrón_2 ;;
*)
comandos por defecto ;;
esac

 si valor no coincide con ningún patrón se ejecutan los comandos después


del *)
o esta entrada es opcional
 patrón puede incluir comodines y usar el símbolo | como operador OR

8
Ejemplo:
#!/bin/bash
echo -n "Respuesta:" read RESPUESTA
case $RESPUESTA in
S* | s*)
RESPUESTA="SI";;
N* | n*)
RESPUESTA="NO ";;
*)
RESPUESTA="PUEDE";;
esac
echo $RESPUESTA

Lazos FOR

for var in lista


do
comandos
done
var toma los valores de la lista

Ejemplos

LISTA="10 9 8 7 6 5 4 3 2 1"
for var in $LISTA
do
echo $var
done

dir="/var/tmp"
for file in $dir/*.bak
do
rm -f $file
done
Sintaxis alternativa, similar a la de C
LIMIT=10
for ((a=1, b=LIMIT; a <= LIMIT; a++, b--))
do
echo "$a-$b"
done

9
Bucle WHILE

while comando
do
comandos
done

 se ejecuta mientras que el código de salida de comando sea cierto

Ejemplo:
while [ $1 ]
do
echo $1
shift
done

Bucle UNTIL

until comando
do
comandos
done

 se ejecuta hasta que el código de salida de comando sea hace cierto

Ejemplo:
until [ "$1" = ""]
do
echo $1
shift
done

BREAK & CONTINUE

Permiten salir de un lazo (break) o saltar a la siguiente iteración (continue)

 break permite especificar el número de lazos de los que queremos salir


(break n)

10
Ejemplo con break:
# Imprime el contenido de los ficheros hasta que
# encuentra una línea en blanco
for file in $*
do
while read buf
do
if [ -z "$buf"]
then
break 2
fi
echo $buf
done < $file
done

Ciclos de Control
Los dos tipos principales de ciclos son:
- el ciclo While
- el ciclo For
El ciclo while permite ejecutar un conjunto de comandos de forma repetida hasta
que una condición ocurra.
El ciclo for permite ejecutar un conjunto de comandos de forma repetida por cada
elemento en una lista.

El ciclo While
La sintaxis básica del ciclo while es:
while comando
do
sentencias
done
Donde comando es normalmente una expresión del comando test (aunque
también puede ser un comando para ejecutar).
sentencias se refiere a el cuerpo del ciclo while y contiene el código a ejecutar en
cada iteración del ciclo. Las sentencias do y done son utilizadas por el comando
while para saber en qué partes inicia y termina el ciclo.
La ejecución de un ciclo while es de la siguiente manera:
1.- se ejecuta el comando
2.- si el código de salida del comando es diferente de cero, el ciclo no se ejecuta

11
3.- si el código de salida del comando es cero, las sentencias del cuerpo del ciclo se
ejecutan
4.- se regresa al paso numero 1
Si tanto el comando como las sentencias son pocos o muy cortos se puede
codificar de la siguiente manera:
while command; do sentencias; done
Control de flujo
Un pequeño ejemplo que usa el ciclo while para desplegar números del cero al
nueve
x=0
while [ $x -lt 10 ]
do
echo $x
x=$((x+1))
done
Cada vez que el ciclo se ejecuta, se verifica si la comparación inicial [ $x -lt 10 ] es
verdadera, en caso de que no sea verdadera, el ciclo termina.
También se pueden crear comandos while anidados:
while comando1
do
sentencias1
while comando2
do
sentencias2
done
sentencias3
done
Como un ejemplo podríamos ejecutar este código:
x=0
while [ "$x" -lt 10 ]
do
y="$x"
while [ "$y" -ge 0 ]
do
echo -n "$y "
y=$((y - 1))
done
echo
x=$((x+1))
done

12
El ciclo For
A diferencia del ciclo while, el cual sale del ciclo cuando una condición es falsa, el
ciclo for opera en base a una lista de datos. El ciclo for repite un set de comandos
por cada dato en la lista.
La sintaxis básica del ciclo for es:
for variable in dato1 dato2 dato3 ... datoN
do
sentencias
done
Donde variable es el nombre de una variable y dato1 a datoN son secuencias de
caracteres o números separados por espacios. Cada vez que el ciclo for se ejecuta
el valor de cada dato en la lista es almacenado en la variable.
Lo cual significa que las veces que el ciclo for ejecutara las sentencias depende del
número de palabras, datos o sentencias especificados en la lista, por ejemplo:
Si se especificara la siguiente lista de datos en un ciclo for:
a veces no hay nada el ciclo se ejecutaría 4 veces.
Por ejemplo:
for x in 1 2 3 4 5 6 7 8
do
echo $x
done

for archivos in /directorio/*


do
cp $archivos /tmp/respaldo
chmod 777 /tmp/respaldo/$archivos
done
Control de flujo

for x in `cat /etc/hosts`


do
echo "encontre este dato >$x<"
done
o
for x in ${array[@]}
do
echo "valor: $x"
done

13
Control de Ciclos
Cuando revisamos el comando while anteriormente, vimos que el ciclo terminaba
cuando una condición particular se cumplía.
Pero si por alguna razón la condicion nunca se cumple, el ciclo continuara para
siempre. Por ejemplo en el siguiente código:
x=0
while [ x -lt 10 ]
do
echo $x
x=$((x+1))
done
En donde en la comparación nos faltó poner meta carácter ($) en la variable x
Pero a veces es útil crear ciclos infinitos controlados por las sentencias del ciclo,
por ejemplo:
while :
do
x=$((x+1)
if [ $x -gt 100 ]; then
break;
fi
done
El operador : (dos puntos) es un comando del sistema que su valor de ejecución
siempre es 0, por lo cual es útil para crear ciclos while infinitos.
Control de flujo
O por ejemplo, para crear un Daemon:
#!/bin/sh
usuario="administrador@servidor.correo.com"
while :
do
if [ `ps -ef | grep "sshd" | grep -v grep | wc -l` -lt 1 ]; then
# el proceso no esta corriendo!!
echo "aguas!!, el proceso sshd ya no corre" > /tmp/procdaemon.$$
mail -s"aguas!!" $usuario < /tmp/procdaemon.$$
rm /tmp/procdaemon.$$
# tratando de levantar nuevamente el proceso
/etc/rc.d/init.d/sshd stop
/etc/rc.d/init.d/sshd start
fi
sleep 300 # 5 minutos
done

14
Secuencia Condicional CASE … ESAC
Sintaxis :

case <variable> in
<valor> ) <comando> ( la variable es = valor , ejecuta los comandos hasta „;;‟ )
<comando>
;;
<valor> ) <comando>
<comando>
;;
* ) <comando> ( Clausula "otherwise" ó "default" : Si no se cumple alguna
<comando> de las anteriores ejecuta los comandos hasta „;;‟ )
;;
esac ( Igual que if acaba en fi , case acaba en esac )

Ejemplos: minimenu.sh
clear # borrar pantalla
echo "1.- Quien hay por ahi ?" # pintar opciones
echo "2.- Cuanto disco queda ?"
echo "3.- Nada. Salir. "
echo "Cual quieres ? : \c" # el carácter "\c" evita que el echo salte nueva línea
read opcion # "opcion" vale lo que se ha tecleado en pantalla
case "$opcion" in # IMPORTANTE : Poner la variable como "$opcion"

1) who ;; # pues si el señor pulsa <INTRO> daría error al no valer nada.


2) df;;
3) echo "Adios";;
*) echo "Opcion $opcion Es Incorrecta" ;;
Esac

# programa para paginar un fichero con mensaje al final de cada pantalla


# llamar como "mas <ficheros>"
pg -p „Pagina %d : „ -n $*

# programa para seleccionar interactivamente ficheros


# se usa dentro de una pipe como : cat `pick *` | <el comando que se quiera , tal
que lp>

15
for j # no tiene error! esta cosa rara permite coger todos los ficheros del
argumento

do
echo "$j ? \c" >/dev/tty
read resp
case $resp in
s*) echo $j ;; # si escribe "s" ó "si"
n*) break ;; # lo mismo esac
done </dev/tty

# programa para borrar de un directorio los ficheros mas viejos de 7 días


# llamar como "limpia.sh <directorio>"
case $# in
0) echo "Falta argumentos"
exit 1
;;
esac
cd $1 && { find . -type f -mtime +7 -exec rm -f -- {} \; ; }

# programa que saca el date en formato dia/mes/año hora:minuto:segundo


# llamar como "fecha.sh"
d=`date „+%d/%m/%y %H:%M:%S‟`
echo "FECHA Y HORA : $d"
# programa para detectar si alguien inicia sesión
# llamar como "watchfor <nombre_de_usuario>"
# Extraído del "Unix Programming Environment" de Kernighan & Pike
case $# in
0) echo "Sintaxis : watchfor usuario" ;
exit 1 ;;
esac
until who | grep "$1"
do
sleep 60
done

16
Bucles FOR
Sintaxis :

for <variable> in <lista>


do
<.. comandos ..>
Done

El bloque entre "for" y "done" da tantas vueltas como elementos existan en <lista>
, tomando la variable cada uno de los elementos de <lista> para cada iteración . En
esto conviene no confundirlo con los for..next existentes en los lenguajes de tipo
algol (pascal , basic ...) que varían
contadores .

Supongamos un programa que contenga un bucle for de la siguiente manera :

for j in rosa antonio


do
echo "Variable = $j"
done
Y la salida que produce es :
Variable es rosa
Variable es antonio

Explicación : el bloque ha efectuado dos iteraciones (dos vueltas). Para la primera ,


la variable -jtoma
el valor del primer elemento -rosa- , y para la segunda , -antonio-.

En el campo <lista> podemos sustituir la lista por patrones de ficheros para la shell
, la cual
expande dichos patrones por los ficheros correspondientes ; de tal forma que al
escribir
for j in *
la shell cambia el „*‟ por todos los ficheros del directorio actual. Por tanto , el
siguiente programa :
for j in *
do
echo $j
done

17
Equivale al comando „ls‟ sin opciones - merece la pena detenerse un momento para
comprender esto.
Vale también poner en el campo <lista> comillas de ejecución junto con cualquier
comando; la construcción - for j in `cat /etc/passwd` -, por ejemplo, ejecutaría
tantas iteraciones como líneas tuviese dicho fichero, y para cada vuelta, la variable -
j- contendría cada una de las líneas del mismo. Por tanto, valdrían expresiones
como - for j in `who` - para procesar todos los usuarios activos en el sistema , - for j
in `lpstat -o ` - , para procesar todos los listados pendientes , ó - for j in
`ps -e` - para tratar todos los procesos de nuestra sesión.

# programa para si los ficheros de un directorio ocupan más de 5 Mb se


truncan.
# llamar como "trunca.sh <directorio>"
case $# in
0) echo "Falta argumento"
exit 1
;;
esac
cd $1 || echo "No puedo cambiar a $1 - saliendo" ; exit 1
for j in *
do
if [ ! -f $j ]
then
continue
fi
siz=`ls -ld $j | awk „{ print $5 }‟
if [ $siz -gt 5000000 ]
then
echo "Truncando $j"
>$j
fi
done

18
Bucles WHILE
Sintaxis :
while <condición>
do
( ... comandos ... )
Done

Aquí las iteraciones se producen mientras que la <condición> sea verdadera ( o


retorno = 0 ). En
caso que sea falsa ( o retorno != 0 ) , el bucle termina.

La sintaxis de <condición> es igual que en el comando -if- .

Ejemplo :
while [ "$opcion" != "3" ]
do
echo "Meta opcion"
read opcion
done
ó también , utilizando comandos :
echo "Escribe cosas y pulsa ^D para terminar"
while read cosa
do
echo $cosa >> /tmp/borrame
done
echo "Las lineas que has escrito son :"
cat /tmp/borrame
# programa para contar
# llamada : contar.sh <numero>
case $# in
0) echo "Falta argumento"
exit 1
;;
esac
c=0
while [ $c -le $1 ]
do
echo $c
c=`expr $c "+" 1`
done

19
Sintaxis De Las Sentencias De Control
El bash shell soporta un conjunto amplio de sentencias de control estructurado que
nos permiten tomar decisiones o repetir ciertos grupos de comandos con facilidad.

CASE ... IN ... ESAC


La sintaxis de esta sentencia de control es la siguiente:
case e in
p1,1 | p1,2 | … | p1,n1 ) lista de comandos ;;
p1,1 | p1,2 | … | p1,n2 ) lista de comandos ;;

pm,1 | pm,2 | … | pm,n1 ) lista de comandos ;;
esac
Esta sentencia intenta encajar e en alguno de los patrones pi,j y ejecuta la lista de
comandos asociada al primer patrón en que encaje. A continuación se muestra un
ejemplo en el que se desarrolla un sencillo programa que muestra al usuario el
calendario del mes que él mismo decida. El programa acepta un parámetro en el
que el usuario indica el mes que quiere ver ya sea en formato numérico o usando
las tres primeras letras del nombre del mes en cualquier combinación de
mayúsculas o minúsculas. Si el mes seleccionado no es correcto se muestra un
mensaje de error en la pantalla.
$ cat > calendario.bsh
#!/bin/bash
mes=$1
case $mes in
[19]|
10|11|12) ;;
[Ee][Nn][Ee]) mes=1 ;;
[Ff][Ee][Bb]) mes=2 ;;
[Mm][Aa][Rr]) mes=3 ;;
[Aa][Bb][Rr]) mes=4 ;;

[Dd][Ii][Cc]) mes=12 ;;
*) echo Error
exit
;;
esac
set `date`
cal $mes $7
^D
En este programa hemos usado el comando set „date` para obtener el año actual.

20
IF ... THEN ... FI
Este comando permite bifurcar la ejecución de un shell script en función a un
conjunto de expresiones condicionales. Su sintaxis es la siguiente:
if l1
then
l2
elif l3
then
l4
elif l5
then
l6

else
ln
fi
El comando if ejecuta inicialmente la lista de comandos l1. Si el último comando de
esta lista tiene éxito (devuelve el código 0), entonces se ejecuta la lista de
comandos l2. Si el último comando falla se repite el mismo esquema con cada una
de las ramas elif. Si no se ejecuta con éxito la sentencia asociada a ninguna de ellas
entonces se ejecuta la lista de sentencias asociada a la rama else. Tanto las ramas
elif como la rama else son opcionales.
A continuación se muestra un sencillo ejemplo que ilustra el comando if.
$ cat > if.bsh
#!/bin/bash
echo "Teclee un número: "
read num
if (( num > 0 ))
then
echo $num es positivo
elif (( num == 0 ))
echo $num es nulo
else
echo $num es negativo
fi
^D
$ chmod ugo+x if.bsh
$ if.bsh
Teclee un número:
12

21
12 es positivo
$ if.bsh
Teclee un número
1
1
es negativo
En este ejemplo hemos hecho uso por primera vez del comando read que juega un
papel complementario a echo, pues sirve para leer datos desde el terminal.

FOR ... DO ... DONE


Los bucles for permiten ejecutar una lista de comandos en varias ocasiones bajo el
control de una variable que toma en cada iteración un valor diferente.
A continuación mostramos la sintaxis:
for v in c1 c2 … cn
do
lista de sentencias
done
El comando for ejecuta la lista de sentencias que se le indica asignando en cada
vuelta uno de los valores c1 c2 … cn a la variable de control v. Para especificar los
valores que toma la variable de control se pueden usar patrones arbitrarios que se
sustituirán por los nombres de los ficheros que encajen en los mismos.
En el ejemplo que se muestra a continuación se desarrolla un pequeño programa
que muestra los nombre de todos los ficheros de código C que residen en el
directorio actual y en el /tmp.
$ cat > for.bsh
#!/bin/bash
for f in "Los ficheros de código C son: " *.c /tmp/*.c
do
echo $f
done
^D
$ chmod ugo+x for.bsh

22
WHILE ... DONE
La sintaxis de este comando es la siguiente:
while l1
do
l2
done
while ejecuta inicialmente la lista de comandos l1 y finaliza si el último comando en
ella falla. En otro caso ejecuta la lista de comandos l2 y a continuación repite el
mismo esquema una y otra vez. En el siguiente ejemplo se desarrolla un programa
que solicita al usuario un número hasta que este está entre 1 y 10.
num=0
while (( num < 1 || num > 10 ))
do
read num
done

UNTIL ... DONE


La sintaxis de este comando es la siguiente:
until l1
do
l2
done
until ejecuta inicialmente la lista de comandos l1 y finaliza si el último comando en
ella tiene éxito. En otro caso ejecuta la lista de comandos l2 y a continuación repite
el mismo esquema una y otra vez.
En el siguiente ejemplo se desarrolla un programa que solicita al usuario un
número hasta que este está entre 1 y 10.
num=0
until (( num >= 1 && num <= 10 ))
do
read num
done

23
Estructuras Condicionales y Selectivas
Ambas estructuras de programación se utilizan para escoger un bloque de código
que debe ser ejecutado tras evaluar una determinada condición. En la estructura
condicional se opta entre 2 posibilidades, mientras que en la selectiva pueden
existir un número variable de opciones

Estructuras Condicionales
La estructura condicional sirve para comprobar si se ejecuta un bloque de código
cuando se cumple una cierta condición. Pueden anidarse varias estructuras dentro
de los mismos bloques de código, pero siempre existe una única palabra fi para
cada bloque condicional.
La tabla muestra cómo se representan ambas estructuras en BASH.

Aunque el formato de codificación permite incluir toda la estructura en una línea,


cuando ésta es compleja se debe escribir en varias, para mejorar la comprensión
del programa. En caso de teclear la orden compleja en una sola línea debe tenerse
en cuenta que el carácter separador (;) debe colocarse antes de las palabras
reservadas: then, else, elif y fi.
Hay que resaltar la versatilidad para teclear el código de la estructura condicional,
ya que la palabra reservada then puede ir en la misma línea que la palabra if, en la
línea siguiente sola o conjuntamente con la primera orden del bloque de código, lo
que puede aplicarse también a la palabra else).
Puede utilizarse cualquier expresión condicional para evaluar la situación,
incluyendo el código de salida de un mandato o una condición evaluada por la
orden interna test. Este último caso se expresa colocando la condición entre
corchetes (formato: [ Condición ]).

24
Véanse algunos sencillos ejemplos de la estructura condicional simple extraídos del
“script” /etc/rc.d/rc.sysinit. Nótese la diferencia en las condiciones sobre la salida
normal de una orden –expresada mediante una sustitución de mandatos– y
aquellas referidas al estado de ejecución de un comando (si la orden se ha
ejecutado correctamente o si se ha producido un error).

# La condición más simple escrita en una línea:


# si RESULT>0; entonces rc=1
if [ $RESULT -gt 0 ]; then rc=1; fi
#
# La condición doble:
# si la variable HOSTNAME es nula o vale “(none)”; entonces ...
if [ -z "$HOSTNAME" -o "$HOSTNAME" = "(none)" ]; then
HOSTNAME=localhost
fi
#
# Combinación de los 2 tipos de condiciones:
# si existe el fichero /fastboot o la cadena “fastboot” está
# en el fichero /proc/cmdline; entonces ...
if [ -f /fastboot ] || grep -iq "fastboot" /proc/cmdline \
2>/dev/null; then
fastboot=yes
fi
Obsérvense los ejemplos para las estructuras condicionales complejas, basados
también en el programa de configuración /etc/rc.d/rc.sysinit.

# Estructura condicional compleja con 2 bloques:


# si existe el fichero especificado, se ejecuta; si no, se da
# el valor “no” a la variable NETWORKING
if [ -f /etc/sysconfig/network ];
then
. /etc/sysconfig/network
else
NETWORKING=no
fi
# Estructura anidada:
# si rc=0; entonces ...; si no, si rc=1; entonces ...; en caso
# contrario; no se hace nada.
if [ "$rc" = "0" ]; then
success "$STRING"

25
echo
elif [ "$rc" = "1" ]; then
passed "$STRING"
echo
fi

Por último, evaluar el siguiente ejercicio:


if [ -f /etc/sysconfig/console/default.kmap ]; then
KEYMAP=/etc/sysconfig/console/default.kmap
else
if [ -f /etc/sysconfig/keyboard ]; then
. /etc/sysconfig/keyboard
fi
if [ -n "$KEYTABLE" -a -d "/usr/lib/kbd/keymaps" -o -d
"/lib/kbd/keymaps" ]; then
KEYMAP=$KEYTABLE
fi
fi

Estructura Selectiva
La estructura selectiva evalúa la condición de control y, dependiendo del resultado,
ejecuta un bloque de código determinado. La siguiente tabla muestra el formato
genérico de esta estructura.

Las posibles opciones soportadas por la estructura selectiva múltiple se expresan


mediante patrones, donde puede aparecer caracteres comodines, evaluándose
como una expansión de ficheros, por lo tanto el patrón para representar la opción
por defecto es el asterisco (*).
Dentro de una misma opción pueden aparecer varios patrones separados por la
barra vertical (|), como en una expresión lógica O.
Si la expresión que se comprueba cumple varios patrones de la lista, sólo se ejecuta
el bloque de código correspondiente al primero de ellos, ya que la evaluación de la
estructura se realiza en secuencia.

26
Obsérvense los siguientes ejemplos:
# Según el valor de la variable UTC:
# - si es “yes” o “true”, ...
# - si es “no” o “false”, ...
case "$UTC" in
yes|true) CLOCKFLAGS="$CLOCKFLAGS --utc";
CLOCKDEF="$CLOCKDEF (utc)";
;;
no|false) CLOCKFLAGS="$CLOCKFLAGS --localtime";
CLOCKDEF="$CLOCKDEF (localtime)";
;;
Esac

Y, como en los casos anteriores, describir el modo de ejecución de la siguiente


estructura selectiva:
case "$SO" in
AIX) echo –n "$US: "
lsuser -ca expires $US|fgrep -v "#"|cut -f2 -d:`"
;;
SunOS) echo "$US: `logins -aol $US|cut -f7 -d:`"
;;
Linux) echo "$US: `chage -l $US|grep Account|cut -f2 -d:`"
;;
*) echo "Sistema operativo desconocido" ;;
esac

27
Bucles
Los bucles son estructuras reiterativas que se ejecutan repetitivamente, para no
tener que teclear varias veces un mismo bloque de código. Un bucle debe tener
siempre una condición de salida para evitar errores provocados por bucles infinitos.
La siguiente tabla describe las 2 órdenes especiales que pueden utilizarse para
romper el modo de operación típico de un bucle.

Los siguientes puntos describen los distintos bucles que pueden usarse tanto en un
guión como en la línea de mandatos de BASH.

Bucles Genéricos
Los bucles genéricos de tipos “para cada” ejecutan el bloque de código para cada
valor asignado a la variable usada como índice del bucle o a su expresión de
control. Cada iteración debe realizar una serie de operaciones donde dicho índice
varíe, hasta la llegar a la condición de salida.
El tipo de bucle for más utilizado es aquél que realiza una iteración por cada
palabra (o cadena) de una lista. Si se omite dicha lista de valores, se realiza una
iteración por cada parámetro posicional.

Por otra parte, BASH soporta otro tipo de bucle iterativo genérico similar al usado
en el lenguaje de programación C, usando expresiones aritméticas. El modo de
operación es el siguiente:
· Se evalúa la primera expresión aritmética antes de ejecutar el bucle para dar un
valor inicial al índice.
· Se realiza una comprobación de la segunda expresión aritmética, si ésta es falsa se
ejecutan las iteraciones del bucle. Siempre debe existir una condición de salida
para evitar que el bucle sea infinito.
· como última instrucción del bloque se ejecuta la tercera expresión aritmética –que
debe modificar el valor del índice– y se vuelve al paso anterior.

28
La siguiente tabla describe los formatos de los bucles iterativos genéricos (de tipo
“para cada”) interpretados por BASH.

Véanse algunos ejemplos:


# Se asigna a la variable “library” el camino de cada uno de
# los archivos indicados en la expansión de ficheros y se
# realizan las operaciones indicadas en el bloque de código.
for library in /lib/kernel/$(uname -r)/libredhat-kernel.so* ; do
ln -s -f $library /lib/
ldconfig -n /lib/
done
...
# Se establece un contador de hasta 20 iteraciones para
# ejecutar el bucle.
for (( times = 1; times < 20; times++ )); do
/usr/sbin/rpcinfo -p | grep ypbind > /dev/null 2>&1 && \
ypwhich > /dev/null 2>&1
done
Y el ejercicio a evaluar:
for US in `cut -sf2 -d: /home/cdc/*.lista`; do
grep "^$US:" /etc/shadow | cut -sf1-2 -d: >>$FICHTEMP
done

29
Bucles Condicionales While & Until
Los bucles condicionales evalúan la expresión en cada iteración del bucle y
dependiendo del resultado se vuelve a realizar otra iteración o se sale a la
instrucción siguiente.
La siguiente tabla describe los formatos para los 2 tipos de bucles condicionales
soportados por el intérprete BASH.

Ambos bucles realizan comparaciones inversas y pueden usarse indistintamente,


aunque se recomienda usar aquél que necesite una condición más sencilla o
legible, intentando no crear expresiones negativas. Véase el siguiente ejemplo:
# Mientras haya parámetros que procesar, ...
while [ $# != 0 ] ; do
processdir "$1"
shift
done
Se proponen como ejercicios convertir este bucle while en un bucle until y en uno
for de estilo C.
i=5
while [ $i -ge 0 ] ; do
if [ -f /var/log/ksyms.$i ] ; then
mv /var/log/ksyms.$i /var/log/ksyms.$(($i+1))
fi
i=$(($i-1))
2done

30
Bucle de Selección Interactiva
La estructura select no es propiamente dicho un bucle de programación
estructurada, ya que se utiliza para mostrar un menú de selección de opciones y
ejecutar el bloque de código correspondiente a la selección escogida. En caso de
omitir la lista de palabras, el sistema
presenta los parámetros posicionales del programa o función. Este tipo de bucles
no suele utilizarse.
La siguiente tabla describe el formato del bucle interactivo.

31
CONCLUSIONES

El programar en shell es muy similar a un oficio común, por ejemplo: un carpintero.


Un carpintero tiene una caja de herramientas que contiene todas las cosas que
utiliza para su oficio, en esa caja puede haber desarmadores, tornillos, taladros, etc.
El carpintero utiliza estas herramientas de diferente manera y en diferentes
combinaciones para lograr resultados diferentes, no se utiliza la misma herramienta
para hacer un juguete que para hacer un escritorio y es posible que si se utilice la
misma no se utilice en la misma intensidad o forma.
Aplicando estas mismas herramientas, el carpintero es capaz de construir los
diferentes elementos necesarios para construir sus proyectos.
Para construir algún objeto de madera, se necesitan las herramientas correctas. En
Unix, las herramientas que se utilizan son llamadas "utilerías" o "comandos". Existen
comandos simples como ls y cd, y existen herramientas más complejas como awk,
sed, y el mismo shell. Uno de los problemas más comunes de trabajar con madera,
es la de utilizar la herramienta o técnica incorrecta para construir algún proyecto. El
saber que herramienta utilizar, normalmente se obtiene con la experiencia.
Las herramientas más poderosas, normalmente toman más tiempo para entender y
aprovechar.

32
BIBLIOGRAFÍA

1. B. Fox, C. Ramey: “BASH(1)” (páginas de manuales de BASH v2.5a)”. 2.001.


2. C. Ramey, B. Fox: “Bash Reference Manual, v2.5a”. Free Software Foundation, 2.001.
3. Mike G, trad. G. Rodríguez Alborich: “Programación en BASH – COMO de
Introducción”. 2.000.
4. M. Cooper: “Advanced Bash-Scripting Guide, v2.1”. Linux Documentation Project,
2.003.
5. R. M. Gómez Labrador: “Administración de Sistemas Linux Red Hat”. Secretariado de
Formación Permanente del PAS (Universidad de Sevilla), 2.002.

MESOGRAFÍA

i. Proyecto GNU.: http://www.gnu.org/


ii. The Linux Documentation Project (TLDP): http://www.tldp.org/
iii. Proyecto HispaLinux (LDP-ES): http://www.hispalinux.es/

33

Você também pode gostar