Programación del Shell LinuxAquí tenemos un libro libre y completo sobre ShellLa sed del "conocimiento libre" es muy bienvenida. |
Comandos Shell Script |
![]() |
|
Home |
Artículos ![]() ![]() |
Comprar el libroChangelogs |
|
Conversación de Bar - Parte II- Mozo! Trae un "chopps" y dos "pastel". Mi amigo hoy no va a beber porque finalmente le está siendo presentado un verdadero sistema operativo y todavia tiene muchas cosas que aprender! - Y entonces, amigo, estas entendiendo todo lo que te expliqué hasta ahora? - Entendiendo estoy, pero no vi nada práctico en eso... - Calma, lo que te dije hasta ahora, sirve como base para lo que ha de venir de aquí en adelante. Vamos a usar estas herramientas que vimos para montar programas estructurados, que el Shell te permite. Entonces verás por qué hasta en la TV hubo un programa llamado "El Shell es el Límite". - Para comenzar vamos a hablar de los comandos de la familia - - Por supuesto, Me quedo con el
|
Posición | 1ª | 2ª | 3ª | 4ª |
---|---|---|---|---|
- |
||||
Valores Posibles | - |
r |
w |
x |
- |
- |
s (suid) |
Así, para descubrir todos los archivos ejecutables en un determinado directorio debería hacer:
Donde nuevamente usamos el circunflejo (^
) para limitar la búsqueda al inicio de cada línea, entonces las líneas listadas serán las que comienzan por un trazo (-
), seguido de cualquier cosa (el punto cuando es usado como una expresión regular significa cualquier cosa), nuevamente seguido de cualquier cosa, y siguiendo un x
o un s
.
Obtendríamos el mismo resultado si hiciéramos:
y agilizaríamos la búsqueda.
Vamos a comenzar a desarrollar programas, me parece que montar un banco de datos de músicas es muy útil y didáctico (y además práctico, en estos tiempos de downloads de mp3 y "quemadores" de CDs). No te olvides que, de la misma forma vamos a desarrollar una cantidad de programas para organizar tus CDs de música, con pequeñas adaptaciones, puedes hacer lo mismo con los CDs de software que vienen con la Linux Magazine y otros que compres o quemes, si compartes este banco de software para todos los que trabajan contigo (el Linux es multiusuario, y como tal debe ser explotado), ganarás muchos puntos con tu adorado jefe.
- Un momento! De donde voy la recibir los datos de los CDs?
- Inicialmente, te voy a mostrar como tu programa puede recibir parámetros de quién lo esté ejecutando y en breve, te enseñaré a leer los datos por la pantalla o de un archivo.
El visual del archivo músicas será el siguiente:
nombre del álbum^intérprete1~nombre de la música1:..:intérprete~nombre de la música
o sea, el nombre del álbum será separado por un circunflejo (^
) del resto del registro, que está formado por diversos grupos compuestos por el intérprete de cada música del CD y la respectiva música interpretada. Estos grupos son separados entre sí por dos-puntos (:
) e internamente, el intérprete será separado por una tilde (~
) del nombre de la música.
Escribiré un programa llamado musinc
, que incluirá registros en mi archivo músicas. Pasaré el contenido de cada álbum como parâmetro en la llamada del programa de la siguiente forma:
De esta forma el programa musinc
estará recibiendo los datos de cada álbum como si fuera una variable. La única diferencia entre un parámetro recibido y una variable es que los primeros reciben nombres numéricos (nombre numérico suena algo raro, no?). Lo que quise decir es que sus nombres son formados por un y solamente un algarismo), el sea $1, $2, $3, ..., $9
. Vamos, antes de todo, hacer un test:
Ejemplos
Vamos a ejecutarlo:
Opa! Me olvidé de hacerlo ejecutable. Voy a hacerlo de forma que permita que todos puedan ejecutarlo y en seguida voy a testearlo:
Repara que la palabra verificar
, que sería el cuarto parámetro, no fue listada. Esto sucedió justamente porque el programa test solo listaba los tres primeros parámetros. Vamos ejecutarlo de otra forma:
Las comillas no dejaron que el Shell
viese el espacio en blanco entre las palabras y las consideró como un único parámetro.
Ya que estamos hablando de pasar parámetros observa bien lo siguiente:
Significado de las Principales Variables Referentes a los Parámetros | |
---|---|
$* |
Contiene el conjunto de todos los parámetros (muy parecido con $@ ) |
Variable | Significado |
$0 |
Contiene el nombre del programa |
$# |
Contiene la cuantidad de parámetros pasados |
Ejemplos
Vamos a alterar el programa test
para usar las variables que acabamos de ver. Vamos hacerlo así:
Repare que antes de las comillas usé una barra invertida para esconderlas de la interpretación del Shell (si no usase las contrabarras las comillas no aparecerian). Vamos a ejecutarlo:
Como ya dije, los parámetros reciben números de 1
a 9
, pero eso no significa que no puedo usar más de 9 parámetros, significa solamente que solo puedo direccionar 9. Vamos a verificar eso:
Ejemplo:
Vamos a ejecutarlo:
Dos cosas muy interesantes en este script:
$1
a $9
hice un echo $11
y que pasó? El Shell interpretó como que era $1
seguido del algarismo 1
y listó pasando1
;
shift
cuya sintáxis es shift n
, pudiendo el n
asumir cualquier valor numérico (sin embargo su default es 1
, como en el ejemplo dado), desprecia los n
primeros parámetros, devolviendo el parámetro de orden n+1
, el primero o sea, el $1
.
Bueno, ahora que ya sabes más sobre pasar parámetros que yo mismo, vamos a volver a nuestra "CDteca" para hacer el script que incluira los CDs en mi banco llamado musicas
. El programa es muy simple (como todo en Shell) y voy a listarlo para que lo veas:
Ejemplos
El script es fácil y funcional, me limito a añadir al final del archivo musicas
el parámetro recibido. Vamos a incluir 3 álbumes para ver si funciona (y para no hacerlo muy aburrido, voy a suponer que en cada CD existem solamente 2 músicas):
Muestro ahora el contenido de musicas.
No es tan funcional como esperaba que quedase... podía haber quedado mejor. Los álbumes están fuera de orden, dificultando la búsqueda. Vamos a alterar nuestro script y después a probarlo nuevamente:
Vamos a incluir un álbum más:
Ahora vamos a ver lo que pasó con el archivo musicas
:
Simplemente incluí una línea que clasifica el archivo musicas
dándole la salida sobre si mismo (para eso sirve la opción -o
), después de que cada álbum fue incluído.
Opa! Ahora está quedando bien y casi funcional. Pero atención, no te desesperes! Esta no es la versión final. El programa quedará mucho mejor y más amigable, en una nueva versión que haremos después que aprendamos la adquirir los datos de la pantalla y a formatear la entrada
Ejemplos
Usar el comando cat
para listar no es una buena idea, vamos a hacer un programa llamado=muslist=, para listar un álbum cuyo nombre será pasado como un parámetro:
Vamos a ejecutarlo, buscando el album 2
. Como ya vimos anteriormente, para pasar la cadena de caracteres album 2
es necesario protegerla de la interpretación del Shell, así él no la interpreta como dos parámetros separados. Vamos a hacerlo de la siguiente forma:
Que desorden! Donde está el error?. Tuve buen cuidado de colocar el parámetro pasado entre comillas, para que el Shell no lo diviera en dos!
Si, pero advierte ahora como el grep
está siendo ejecutado:
grep $1 musicas
Aunque coloque álbum 2
entre comillas, para que fuera visto como un único parámetro, cuando el $1
fue pasado por el Shell hacia el comando grep
, lo transformó en dos argumentos. Así, el contenido final de la línea que el comando grep
ejecutó fue el siguiente:
grep album 2 musicas
Como la sintáxis del grep
es:
grep <cadena de caracteres> [arch1, arch2, ..., archn]
el grep
entendió que debería recuperar la cadena de caracteres album
en los archivos 2
y musicas
, Al no existir el archivo 2
generó el error, y como encontro la palabra album
en todos los registros de musicas
, los listo todos.
cadena de caracteres
a ser pasada hacia el comando grep
posea blancos o TAB
, y lo mismo que dentro de variables, colóquela siempre entre comillas para evitar que las palabras después del primer espacio en blanco o TAB
sean interpretadas como nombres de archivos.
Por otro lado, es mejor ignorar las mayúsculas y minúsculas en la búsqueda. Resolveríamos los dos problemas si el programa tuviera la siguiente forma:
En este caso, usamos la opción -i
del grep
, que como vimos, sirve para ignorar mayúsculas y minúsculas, y colocamos el $1
entre comillas, para que el grep
continue viendo la cadena de caracteres resultante de la expansión de la línea por el Shell
como un único argumento de búsqueda.
Ahora, nota que el grep
localiza la cadena buscada en cualquier lugar del registro, entonces de la forma que estamos lo haciendo, podemos buscar por álbum, por música, por intérprete o hasta por un pedazo de cualquiera de estos. Cuando conozcamos los comandos condicionales, montaremos una nueva versión de muslist
que permitirá especificar por que campo buscar.
Ahora me vas a decir:
- Si, todo bien, pero es muy tedioso tener que colocar el argumento de búsqueda entre comillas cuando tengo que pasar el nombre del álbum. Esta forma no es nada amigable!
- Tienes toda la razón, y es por eso que te voy a mostrar otra forma de hacer lo que me pediste:
De esta forma, el $*
, que significa todos los parámetros, será substituído por la cadena album 2
(de acuerdo con el ejemplo anterior), haciendo lo que tu querias.
No te olvides que el problema del Shell no es si él puede o no hacer una determinada cosa. El problema es decidir cuál es la mejor forma de hacerla, ya que para realizar cualquier tarea, la cantidad de opciones es enorme.
Recuerdas aquel dia de verano fuiste a la playa?, olvidaste el CD en el automóbil, y entonces aquel "solecito" de 40 grados dobló tu CD y ahora necesitas una herramienta para borrarlo del banco de datos. No hay ningún problema, vamos a desarrollar un script llamado musexc
, para excluir estos CDs.
Antes de desarrollar el programa te quiero presentar una opción bastante útil de la familia de comandos grep
. Es la opción -v
, que cuando es usada, lista todos los registros de la entrada, excepto el(los) localizado(s) por el comando. Veamos:
Ejemplos
De acuerdo con lo que te expliqué antes, el grep
del exemplo listó todos los registros de músicas excepto los referentes al album 2
, porque atendía al argumento del comando. Estamos entonces preparados para desarrollar un script para retirar aquél CD doblado de tu "CDteca". Este script tiene la forma siguiente:
En la primera línea mandé hacia /tmp/mus$$
el archivo musicas, sin los registros que tuviesen la consulta hecha por el comando grep
. En seguida, moví (que, en realidad, equivale a renombrarlo) /tmp/mus$$
al antiguo musicas
.
Usé el archivo /tmp/mus$$
como archivo de trabajo, porque como ya habia citado en el artículo anterior, el $$
contiene el PID
(Process Identification o identificación del proceso) y de esta forma cada uno que edite el archivo musicas
lo hará en un archivo de trabajo diferente, de esta forma evitamos choques en su uso.
- Y entonces, amigo, estos programas que hicimos hasta aquí son muy rústicos en virtud de la falta de herramientas que todavia tenemos. Pero están bien, mientras me tomo otro "chopp", puedes ir para casa a praticar en los ejemplos dados porque, te prometo, llegaremos a desarrollar un sistema bien bonito para el control de tus CDs.
- Cuando nos encontremos la próxima vez, te voy a enseñar como funcionan los comandos condicionales y mejoraremos otro poco estos scripts.
- Por hoy es suficiente! Ya hablé demasiado y necesito mojar las palabras porque estoy con la garganta seca!
- Mozo! Otro sin y espuma!
Cualquer duda o falta de compañia para tomar una cerveza o hasta para hablar mal de los políticos, lo único que tienes que hacer es mandarme un e-mail para julio.neves@gmail.com. Voy aprovechar tambiém para mandar mi aviso publicitario: puedes decirle a los amigos que quien quiera hacer un curso nota diez de programación en Shell, que mande un e-mail para julio.neves@uniriotec.br para informarse.
Gracias y hasta la próxima
-- HumbertoPina - 13 Sep 2006