=======Tutorial de Shell de Bourne========
Este tutorial historico presenta algunos metodos y comandos que lo ayudaran a hacer expeditas las tareas diarias que se realizan con el interprete de comandos en UNIX System V, la Bourne Shell. Logicamente al ser una shell de 1985, no todos se aplican a los actuales BSD o GNU con Linux, pero si la mayoria de ellos.
La primer seccion de este tutorial "Lenguaje de Comandos de la shell", introduce algunos atajos basicos y comandos que ayudaran a realizar de forma rapida y sencilla algunas tareas en el sistema UNIX. La segunda seccion de este tutorial "Programacion de la Shell", le ensenara como colocar dichas tareas en un fichero y pedirle a la shell que ejecute los comandos contenidos en el fichero.
Lenguaje de Comandos de la Shell
El lenguaje de la shell tiene caracteres especiales que le ofrecen algunos atajos para realizar tareas en la shell. Estos caracteres especiales se listan abajo y se discuten en esta seccion del tutorial.
Estos son metacaracteres. Un metacaracter es un caracter que tiene un significado especial en el lenguaje de comandos de la shell.
Metacaracter | Significado |
---|---|
* [ ] |
Estos metacaracteres ofrecen atajos para los nombres de ficheros |
& |
Este caracter pone comandos ne segundo plano. Mientras la shell ejecuta los comandos en segundo plano, la terminal quedara libre para que haga otras tareas. |
; |
Este caracter permite pitear varios caracters en una sola linea. Cada comando debe terminar con una ; . Cuando ingrese la tecla intro, cada comando se ejecutara secuencialmente desde el comienzo de la linea la final de la linea. |
\ |
Este caracter permite desactivar el significado de los metacaracteres tales como * , ? , [ , ] , & y ; . |
"..." '...' |
Tanto las citas entrecomilladas como apostrofadas desactivan el significado delimitante del espacio en blanco, y el significado especial de los metacaracteres. Sin embargo, las comillas permiten que los caracteres $ y \ retengan su significado especial (el $ y la \ se discuten mas adelante y son importantes para los programas de shell). |
Metacaracteres
El significado de los metacaracteres es similar a decir "etc, etc, etc", "todo lo anterior", o "uno de esos". Al usar metacaracters para todo o una parte de un nombre de fichero se le dice "generacion de nombre de fichero" Es una manera rapida y facil de referirse a los nombres de ficheros.
*
*
Este metacaracter coincide con "todo", cualquier
cadena de caracteres, incluyendo una que no tenga caracteres en lo
absoluto.
El *
solo refiere a todos los nombres de fichero en el
directorio actual, el directorio en el que se encuentra en este momento.
Para ver los efectos del *
. intenta el siguiente
comando:
echo *
El comando echo mostrara sus argumentos en su terminal. La respuesta del sistema a echo * deberia haber siddo un listado de todos los nombres de fichero en el directorio actual. Sin embargo, a diferencia de ls, los nombres de fichero apareceran en lineas horizontales en lugar de hacerlo en un listado vertical.
Como puede que no haya usado anteriormente el comando echo, he aqui una pequena ayuda memoria del comando.
Sea muy cuidadoso con
*
ya que es un caracter poderoso. Si lo incluye en rm * borrara todos los ficheros en su directorio actual.
El metacaracter *
tambien se usa para expandir los
nombres de ficheros en el directorio actual. Si ha escrito varios
informes y los ha nombrado
reporte
reporte1
reporte1a
reporteb.01
reporte25
reporte316
entonces
reporte*
se referira a los seis reportes en el directorio actual. Si desea
encontrar cuantos reportes ha escrito, podria usar el comando
ls para listar todos los reportes que comiencen los las letras
reporte
$ ls reporte*
reporte
reporte1
reporte1a
reporteb.01
reporte25
reporte316
$
El *
se refiere a cualquiera de los caracteres despues
de las letras reporte
, incluyendo si no hay letras algunas
en lo absoluto. Tenga en cuenta que *
llama a los ficheros
en orden numerico y alfabetico. Una manera facil y rapida de imprimir
todos esos reportes en orden es
$ pr reporte*
Elija un caracter que sus nombres de fichero tienen en comun, tal
como una a
, y liste todos esos ficheros en el directorio
actual.
$ ls *a*
El *
puede ser colocado en cualquier lugar en el nombre
de fichero.
$ ls F*E
Este comando hubiese listado los siguientes ficheros en orden
F123E
FATE
FE
Fig3.4E
?
Este metacaracter coincide con cualquier caracter unico.
El metacaracter ?
reemplaza a cualquier caracter unico
del nombre de fichero. Si ha creado texto de varios capitulos de un
libro, pero solo quiere listar los capitulos que sabe que ha escrito
hasta el capitulo9
, usaria el ?
:
$ ls capitulo?
capitulo1
capitulo2
capitulo5
capitulo9
$
Aunque ?
coincide cualquier caracter unico, puede usarlo
mas de una vez en un nombre de fichero. Para listar el resto de los
capitulos hasta capitulo99
, ingrese
$ ls capitulo??
Por supuesto, si desea listar todos los capitulos en el directorio
actual, usaria capitulo*
En ocasiones usa mv o cp con un fichero, accidentalmente presionara un caracter que no imprime en su terminal como parte de su nombre de archivo cuando use ls. Si intenta hacer cat con dicho fichero, le dara un mensaje de error. Los metacaracteres
*
y?
son muy poderosos en llamar al fichero y moverlo al nombre correcto.
Intente el siguiente ejemplo
- Escriba un fichero corto llamado
prueba
- ingresa mv prueba prueba^g1 (recuerda que ^g se hace con Ctrl+g)
- ls prueba1
le dara
prueba1 not found
ingrese
ls prueba?1
le indicara
prueba1
[...]
Estos metacaracteres coinciden un rango especifico de caracteres
[...]
La shell coincide uno de los caracteres
especificados, o rangos de caracteres entrecorchetados.
Los caracteres encerrados entre []
actuan como una forma
especializada de ?
. La shell coincidira solo uno de los
caracteres entrecorchetados en la posicion especificada en el nombre de
fichero. Si usa [crf]
como parte de un nombre de fichero,
la shell buscara por , c
, o r
, o
f
.
$ ls [crf]at
cat
fat
rat
$
La shell tambien buscara un rango de caracteres dentro de los
corchetes. Si usa capitulo[0-5], la shell buscara los nombres
capitulo0
hasta capitulo5
. Esta es una manera
facil de imprimir solo ciertos capitulos a la vez.
$ pr capitulo[2-4]
Este comando imprimira los contenidos de capitulo2
,
capitulo3
, y capitulo4
en dicho orden.
La shell tambien busca un rango de letras. Para [A-Z]
la
shell buscara letras en mayusculas, o para [a-z]
buscara
letras minusculas.
Intenta cada uno de esos metacaracteres en ficheros de su directorio actual.
&
El caracter &
puesto al final de una linea de
comandos, ejecuta la tarea en segundo plano.
Algunos comandos de shell requieren tiempo considerable para su cumplimiento. Es conveniente dejar que dichos comandos corran en segundo plano para dejar libre su terminal de manera que pueda continuar haciendo otras tareas mientras tanto. La sintaxis general de un comando que se ejecuta en segundo plano es
comando &
El comando grep puede desarrollar busquedas
intensivas, que pueden requerir cierto tiempo en completarse. Si pone el
comando grep en modo segundo plano, podra continuar haciendo
alguna otra tarea en su terminal mientras se realiza la busqueda por la
shell. En el ejemplo siguiente, el modo segundo plano se usa mientras se
buscan en todos los ficheros del directorio los caracteres
palabra
. El &
es el ultimo metacaracter
del comando.
$ grep palabra * &
21940
$
21940
es el numero de proceso. Este numero
(PID) es esencial si desea detener la ejecucion de un comando en segundo
plano. Esto se discutira en ejecutar y terminar
procesos
En la siguiente seccion de este tutorial vera como redirigir la respuesta del sistema del comando grep a un fichero de modo que no se muestre en un terminal e interrumpa su trabajo actual. Luego, podra observar el fichero cuando haya finalizado su tarea.
;
El metacaracter ;
realiza ejecucion secuencial de
comandos indicados en una linea, y separados un ;
.
Si desea introducir varios comandos en una linea, debe separar cada
uno de ellos con un ;
. La sintaxis general para poner
comando1
, comando2
y comando3
en
una linea de comandos es el siguiente:
$ comando1; comando2; comando3
La ejecucion secuencial es muy util cuando necesita ejecutar varios
comandos de shell mientras se encuentra en el editor de lineas ed. Intente ingresar varios comandos separados por
una ;
. Tenga en cuenta que luego de presionar la
tecla Intro, el sistema responde a cada comando en el
orden en el cual aparecen en la linea de comandos:
$ cd; pwd; ls; ed prueba
La shell ejecutara los comandos de manera secuencial:
Orden | Comando | Accion |
---|---|---|
1 | cd |
cambia al directorio de usuario |
2 | pwd |
imprime el directorio actual |
3 | ls |
lista los ficheros en el directorio actual |
4 | ed |
prueba ingresar al editor de lineas ed y comenzar por editar el fichero prueba |
¿Noto la rapida rafaga de comandos? Podria no querer que estas veloces respuestas se presenten en su terminal. La seccion de redirigir salida le ensenara a resolver este problema.
#### \
La barra invertida \
desactiva el significado de un
metacaracter.
¿Como busca uno de los caracteres especiales en un fichero? Ingrese
una barra invertida justo antes de ingresar el metacaracter. La barra
invertida desactiva el significado especial del siguiente metacaracter
que ingrese. Cree un fichero llamado prueba
que tenga una
linea que contenga la oracion "El juego de las *
. Busque el
caracter *
en el fichero prueba
$ grep \* prueba
El juego de las *
$
Desactivar caracteres especiales por Citado
Todos los caracteres encerrados entre apostrofes '...'
pierden su significado especial.
Todos los caracteres entrecomillados "..."
pierden su
significado, excepto $
, \
y '
Los metacaracteres en la shell pierden su significado especial cuando
van entrecomillados o apostrofados. El apostrofo desactiva el
significado especial de cualquier metacaracter. El entrecomillado
desactiva el significado especial de cualquier metacaracter, con
expresion de $
, \
y '
. Los
caracteres $
, \
y '
son muy
importantes en la programacion de la shell.
Un delimitador separa argumentos, diciendole a la shell donde termina un argumento y comienza otro. El espacio en blanco tiene un significado especial para la shell porque se usa como delimitador entre los argumentos de un comando.
El comando banner usa los caracteres de espacio en blanco para delimitar sus argumentos. Si no ha usado el comando banner intentelo ahora. La respuesta del sistema sera algo sorpresiva.
$ banner feliz navidad para todos
###### ###### # # ######
# # # # #
##### ##### # # #
# # # # #
# # # # #
# ###### ###### # ######
# # ## # # # ##### ## #####
## # # # # # # # # # # # #
# # # # # # # # # # # # # #
# # # ###### # # # # # ###### # #
# ## # # # # # # # # # # #
# # # # ## # ##### # # #####
##### ## ##### ##
# # # # # # # #
# # # # # # # #
##### ###### ##### ######
# # # # # # #
# # # # # # #
##### #### ##### #### ####
# # # # # # # #
# # # # # # # ####
# # # # # # # #
# # # # # # # # #
# #### ##### #### ####
Ahora ingrese
$ banner feliz navidad "para todos"
###### ###### # # ######
# # # # #
##### ##### # # #
# # # # #
# # # # #
# ###### ###### # ######
# # ## # # # ##### ## #####
## # # # # # # # # # # # #
# # # # # # # # # # # # # #
# # # ###### # # # # # ###### # #
# ## # # # # # # # # # # #
# # # # ## # ##### # # #####
##### ## ##### ## ##### #### ##### #### ####
# # # # # # # # # # # # # # # #
# # # # # # # # # # # # # # # ####
##### ###### ##### ###### # # # # # # # #
# # # # # # # # # # # # # # # #
# # # # # # # # #### ##### #### ####
Vea que para todos aparecen en la misma linea del cartelon. El espacio entre para y todos ha perdido su significado especial como delimitador.
Si usa apostrofes en el argumento del comando grep, el
espacio en blanco pierde su significado de delimitador. Puede buscar dos
palabras. La linea El juego de las *
esta en su fichero
prueba
. Busquemos por las dos palabras de las
en el fichero prueba
.
$ grep 'de las' prueba
El juego de las *
$
Intenta desactivar el significado especial de caracter *
usando apostrofados:
grep '*' prueba
El juego de las *
$
Redirigir entrada y salida
La redireccion de entrada y salida son herramientas importantes para realizar muchas tareas de shell y programas.
Redirigir entrada
Puede redirigir el texto de un fichero para que sea la entrada de un
comando. El caracter <
redirige los contenidos de un
fichero en un comando.
La sintaxis general para redirigir los contenidos de un fichero en un comando se muestra a continuacion
$ comando < fichero
Si escribe un reporte a su jefe, es probable que no quiera mecanografiar el comando mail y luego ingresar su texto. Deseara poner el texto del reporte en un editor y corregir errores. Querra correr el fichero a lo largo del comando spell para asegurarse que no ha cometido errores. Puede luego usar mail para enviar el fichero conteniendo su reporte a otro usuario empleando el simbolo de redireccion. En el ejemplo de abajo, se revisa un fichero llamado reporte para corregirlo ortograficamente, y luego se lo redirige a la entrada del comando mail y se lo envia al usuario jefe.
$ spell reporte
$
mail jefe < reporte
$
Ya que la unica respuesta del comando spell es el prompt, no habia palabras mal escritas en reporte. El comando spell es una herramienta util que le da una lista de palabras que no estan en la lista de correccion del diccionario.
Redirigir Salida
Puede redirigir la salida de un comando a los contenidos del un fichero. Cuando redirige la salida en un fichero, puede o bien crear un fichero nuevo, agregar la salida al final de un fichero, o puede borrar los contenidos de un viejo fichero y reemplazarlo con la salida redirigida.
El caracter >
redirige la salida de un comando a un
fichero.
Un simbolo unico de redireccion creara un nuevo fichero, o borrara un fichero viejo y reemplazara sus contenidos con la nueva salida. La sintaxis general para la redireccion de salida se muestra a continuacion:
$ comando > fichero
Si desea que la lista de palabras mal escritas producidas por el
comando spell sean colocadas en un fichero en lugar de aparecer
en su terminal, redirija spell a fichero. En este ejemplo,
spell analizara el fichero memorandum
en busqueda
de palabras mal escritas, y pondra tales palabras en el fichero
malescrito
.
$ spell memorandum > malescrito
$
El comando sort puede ser redirigido a un fichero. Suponga
el un fichero llamado lista
contiene una lista de nombre.
En el siguiente ejemplo, la salida del comando sort listara los
nombres alfabeticamente y redirigira la lista a un nuevo fichero
nombres
.
$ sort lista > nombres
$
Tenga cuidado de escoger un nuevo nombre para el fichero que contendra el listado ordenada alfabeticamente. La shell primero borra los contenidos del fichero que iba a aceptar la salida redirigida, y luego ordena el fichero y coloca su salida en un fichero vacio. Si ingresa
sort lista > lista
la shell borrara lista
y a continuacion no podra ordenar
nada en el nuevo fichero lista
.
Si redirige un comando en un fichero que ya existe, la shell borrara el fichero existente y pondra la salida del comando en dicho fichero. No se le dara advertencia alguna de que esta borrando un nuevo fichero. Si desea asegurarse usted mismo que no es un fichero existente, recurra al comando ls con dicho nombre de fichero como argumento.
De existir el fichero, ls lo listara. Si el fichero no existe, ls le dira que el fichero no fue encontrado en el directorio actual.
[N.d.T. Otras shell implementan la funcion noclobber para evitar este problema.]
El simbolo doble de direccion >>
agrega la salida
de un comando luego de la ultima linea del fichero.
El forma general para agregar salida al final del fichero es
comando >> fichero
En el siguiente ejemplo, los contenidos de prueba2
se
agregan luego de la ultima linea de prueba1
, redirigiendo
la salida del comando cat de prueba2
a
prueba1
El primer comando cat prueba1 muestra los contenidos de
prueba1
. Luego, cat prueba2 muestra los contenidos
de prueba2
. La tercer linea de comandos, *cat prueba2
prueba1, agrega los contenidos de
prueba2
al final del ficheroprueba1
, mientras que cat prueba1* muestra los nuevos contenidos deprueba1
.
$ cat prueba1
hola
esto es una prueba
esta es la ultima linea de este fichero
$
$ cat prueba2
Agrego esto a fichero prueba1
Esta es la ultima linea del fichero prueba2
$
$ cat prueba2
$ cat prueba1
hola
esto es una prueba
Esta es laultima linea de este fichero
Agrego esto a fichero prueba1
Esta es la ultima linea del fichero prueba2
$
En la seccion de #metacaracteres,
uno de los ejemplos demostraba como ejecutar el comando grep en
segundo plano con &
. Ahora, puede redirigir la salida
de dicho comando a un fichero llamado ficheroconpalabras
, y
luego buscar en el fichero cuando ha terminado su tarea actual. el
&
es el ultimo caracter de la linea de comandos.
$ grep palabra * > ficheroconpalabras &
$
|
El caracter |
se llama cano. Redirige la salida
de un comando a la entrada del siguiente comando.
Si dos comandos o mas estan interconectados por medio de un caracter
cano |
, la salida del primer comando es entubada al
siguiente comando, formando parte de la entrada a dicho comando.
La sintaxis general del cano es el siguiente:
$ comando1 | comando2 | comando3
La salida de comando1
se usa como entrada de
comando2
. La salida de comando2
se usa como
entrada de comando3
.
Ya ha intentado presentar un cartelon con banner en su terminal. Puede usar un cano para enviar un saludo de cumpleanos a alguien por correo electronico.
Si el usuario sultano
tiene un cumpleanos, entube el
comando banner con un mensaje de felicitacion al comando
mail:
$ banner feliz cumpleanos | mail sultano
El usuario sultano
recibira un cartelon en su casilla de
correo electronico.
El comando date le da la fecha y la hora. Compruebelo en su terminal
$ date
Mon Nov 25 17:57:21 CST 1985
$
Note que la hora se da desde el 12° caracter hasta el 19° caracter. Si desea saber solo la hora y no la fecha, puede entubar la salida del comando date al comando cut. El comando cut busca caracteres solo en una parte especificada de cada linea de fichero. Si usa la opcion -c, cut escogera solo aquellos caracteres en las posiciones de caracteres especificadas. Las posiciones de caracteres se cuenta desde la izquierda. Para mostrar solo la hora en su terminal, entube la salida del comando date al comando cut, solicitando desde el caracter 12 al 19.
$ date | cut -c12-19
18:08:23
Pueden usarse varios canos en una sola linea de comandos. La salida del ejemplo puede ser entubada al comando banner.
$ date | cut -c12-19 | banner
Intente cada uno de esos ejemplos, y revise la respuesta del sistema.
Luego en este capitulo, escribira un programa de shell que le de la hora.
Sustitucion de salida de comando
Los caracteres de apostrofos invertidos ...
permiten encerrar la salida de cualquier linea de comandos o programa de
shell para sustituirla.
En los teclados de distribucion espanola latinoamericana, el caracter de apostrofo invertido se realiza presionando dos veces la combinacion AltGr+}.
En la seccion programacion de la shell, sustituira la salida de una linea de comandos como valor para una variable.
La salida del comando time puede sustituirse por el argumento en un impreso de banner
$ banner `date | cut -c12-19`
# # # ##### ##### # # #####
## # # # # # # # # # # # # # #
# # # # # # # # # # # # #
# ####### ##### ##### ####### #####
# # # # # # # # # #
# # # # # # # # # # # # #
##### # # ##### ##### # # #####
Ejecutar y Terminar Procesos
Correr comandos en un momento posterior
Cuando ingresa un comando en la linea de comandos de su terminal, el sistema UNIX intenta ejecutarlo de inmediato. Es posible decirle al sistema que ejecute dichos comandos en un momento posterior, con el comando batch o el comando at. Finalice el comando con ^d para dejar que la shell conozca que ha finalizado el listado de comandos a ejecutar.
El comando batch es util si esta ejecutando un proceso o programa de shell que requiere una cantidad mayor a la normal de tiempo de computo. El comando batch produce un trabajo "en lote", que consiste en comandos a ser ejecutados por la computadora. El trabajo forma una cola, y se ejecutara no bien la carga del procesador del sistema descienda hasta un nivel aceptable. Esto libera a la computadora para poder responder rapidamente a otras entradas que le pudiesen efectuar otros o usted mismo.
La sintaxis general de batch es:
$ batch
primer comando
.
.
.
ultimo comando
^d
Si solo existe una linea de comandos, puede usar la siguiente sintaxis:
batch comando
^d
El siguiente ejemplo usa el comando batch para ejecutar el comando
grep en un momento conveniente. Cuando el sistema puede
ejecutar el comando y responder aun rapidamente a otros usuarios,
ejecutara grep para buscar todos los ficheros con la cadena
"justicia social", y redirigira la salida en el fichero
fichero_js
. El uso del comando batch es una
cortesia a otros usuarios de su sistema UNIX.
$ batch grep "justicia social" > fichero-js
^d
job 12828131.b at Mon Dec 7 11:14:54 1985
$
El comando at indica a la computadora un momento especifico para ejecutar dicho comando. La sintaxis general del comando at es:
$ at hora
primer comando
.
.
.
ultimo comando
^d
La hora
debe indicar el momento del dia y luego la fecha
(si la fecha no es el dia de hoy).
Si teme olvidar el cumpleanos de fulana
, puedes usar el
comando at para asegurarte de que se le envie el dia de su
cumpleanos un cartelon hecho con banner, para que le llegue
apenas entra a trabajar:
$ at 8:15 am feb 27
banner Que los cumplas feliz, bonita! Siempre iluminas mi terminal | mail fulana
^d
job 1282923.a at Mon Feb 27 8:15, 1986
Tanto el comando batch y el comando at le proporcionaran un numero de trabajo. Si decide que no desea ejecutar los comandos batch o at que ya estan a la espera en una cola de procesos por lote, puede borrarlos con la opcion -r del comando at, proporcionando el numero de trabajo. La sintaxis general de cancelacion es:
$ at -r nro_trabajo
Como fulana
inicio una relacion sentimental con
sultano
en navidad, borre urgentemente la solicitud de
trabajo por lotes dejada previamente con at. El comando at
-l proporcionara un listado de los trabajos por lotes actuales
batch o at en espera.
$ at -l
: mengano 12828131.b at Mon Dec 7 11:14:54 1985
: mengano 1282923.a at Mon Feb 27 8:15, 1986
(mengano
es su nombre de usuario)
Intenta la siguiente solicitud. Usando el comando at enviate
a ti mismo un fichero al mediodia. El fichero llamado
memorandum
dice que es hora de comer. Debes redirigir el
fichero a mail.
mail $USER < memorandum
^d
job 14694939.a at jun 30 12:00:00 1985
$
$
at -l
: mengano 14694939.a at jun 30 12:00:00 1985
$
Obtener el status de los procesos en ejecucion
El comando ps le dara el status de los proceso que usted esta ejecutando.
El comando ps le dira el status de los comandos en segundo plano discutidos en la seccioon de metacaracteres. En el siguiente ejemplo, se ejecuto grep en el segundo plano, y luego se ingreso el comando ps. La respuesta de la computadora, la salida del comando ps, dio el PID, que es el numero identificador de procesos, y la TTY, que es el identificador asignado a la terminal actual en la que esta logueado. Tambien da el tiempo de ejecucion acumulativo para cada proceso, y el comando que se esta ejecutando. El PID es importante si decide detener la ejecucion de dicho comando.
$ grep palabra * &
28223
$
$
ps
PID TTY TIME Command
28124 10 0:00 sh
28223 10 0:04 grep
28224 10 0:04 ps
$
El ejemplo no solo da el PID del comando grep, sino tambien para los otros procesos que coren, el comando ps en si, y el comando sh que siempre se ejecuta en tanto usted permanezca logueado. sh es el programa de la shell que intepreta los comandos de shell.
Terminar Procesos Activos
El comando kill se utiliza para detener procesos activos de la shell. La sintaxis general del comando kill es:
$ kill PID
¿Que hace si decide que no necesita ejecutar el comando que esta ejecutandose en segundo plano? Si presiona la tecla BREAK o la tecla DEL, decubrira que no detiene los procesos en segundo plano de la misma forma que lo hace con los comandos interactivos. Para ello debe utilizar el comando kill. Si desea terminar el comando grep al que se recurrio en el ejemplo anterior:
$ kill 28223
28223 Terminated
$
Usar el comando nohangup
Otra forma de exterminar todos los procesos es colgar el modem durante la llamada a la computadora, o bien desconectar la sesion. ¿Pero que sucede si desea que los procesos en segundo plano continuen su ejecucion despues de haberse desconectado? El comando nohup le permitira que los comandos en segundo plano continuen, incluso si cierra su sesion desconectandose.
$ nohup comando &
Si coloca un comando nohup como prefijo al comienzo del comando que correra como proceso de segundo plano, el mismo conitnuara ejecutandose hasta finalizar, incluso aunque usted se haya desconectado del sistema.
$ nohop grep palabra * > palabra.lista &
El comando nohup puede exterminarse con el comando kill.
Programacion de la shell
Comenzando
Deje que un guion de shell realice sus tareas por usted. Un guion de shell es un fichero de sistema UNIX que contiene los comandos que usted usaria para desarrollar una tarea programada.
Crear un programa simple de shell
Para crear un guion de shell, usa tu editor de texto favorito e ingresa los siguientes comandos:
pwd
ls
echo Este es el final del guion de shell
Guarda los contenidos escritos en el editor en un fichero llamado dl (por "listado de directorio), y sal del editor. Has creado un guion de shell.
$ cat dl
pwd
ls
echo Este es el final del guion de shell
$
Ejecutar un guion de shell
La manera mas simple de decirle a la shell que queremos ejecutar un programa, es usar el comando sh.
sh dl
Notara que se imprime primero la ruta de directorio del directorio actual, y luego se listara elc contenido del mismo, y finalmente el comentario "Este es el final del guion de shell".
El comando sh resulta una buena maneta para evaluar su guion de shell y asegurarse que funciona.
Si dl le resulta conveniente, querra cambiar los permisos de
fichero de manera que solo se necesario mecanografiar dl
para ejecutarlo. El comando que cambia los permisos de un fichero es
chmod.
$ chmod u+x dl
$ ls -l dl
-rwx------ 1 usuario usuario 48 Nov 14 10:40 dl
Ahora tiene un programa ejecutable llamado dl
el el
directorio actual.
Ejecute el comando ingresando
$ dl
Crear un directorio bin para los ficheros ejecutables
Si su guion de shell le resulto util, querra guardarlo en un
directorio especial llamado bin, dentro de su direcotrio
/home
.
Si desea que su comando dl sea accesible desde todos sus directorios,
haga un directorio bin
desde su directorio home y mueva
alli el fichero dl
.
mkdir ~/bin/
mv dl ~/bin/dl
Cambie al directorio bin e ingrese el comando ls -l
.
¿dl
cuenta auin con permisos de ejecucion?
Ahora muevase a otro directorio distinto a su directorio
/home
. Ingrese dl
. ¿Que sucedio?
El directorio bin/ es el mejor lugar para mantener sus programas de
shell ejecutables. Es posible darle al directorio bin otro nombre, pero
necesitara cambiar la variable de PATH
de la shell para
hacerlo. Las variables de la shell se discuten brevemente en este
capitulo.
Puede darle a su guion de shell cualquier nombre de fichero apropiado. Sin embargo, no deberia nombrar su programa con el mismo nombre de un comando de sistema. El sistema ejecutaria su comando y no el comando de sistema.
Si hubiese nombrado a su programa dl como mv, cada vez que hubiese intentado mover un fichero o renombrarlo, no lo haria. Lo unico que haria su programa ejecutado seria mostrar el nombre de directorio y listar sus contenidos.
Otro problema hubiese ocurrido si usted hubiese llamado a su programa dl como ls, y luego intentado ejecutar el fichero ls. Esto hubiese creado un bucle infinito. Luego de un tiempo, el sistema le hubiese dado un mensaje de error:
too many processes, cannot fork.
¿Que ha sucedido? Tipeo su nuevo comando ls. La shell leyo el comando pwd y ejecuto dicho comando. Luego la shell leyo el comando ls en su fichero e intento ejecutar su comando ls. Esto formo el bucle infinito.
Los programadores del sistema UNIX sabiamente establecieron un limite de cantidad a las ejecuciones en bucle, para impedir que sean infinitas. Una manera de evitar que esto suceda es darle un nombre de ruta al comando ls del sistema: /bin/ls
El siguiente programa ls deberia funcionar:
$ cat ls
pwd
/bin/ls
echo Este es el final del guion de shell
$
Si usted hubiese nombrado su comanbdo ls, entonces, entonces solo podria ejecutar el comando de sistema con /bin/ls.
Variables
Si le gusto enviar el cartelon de cumpleanos con el comando banner, podria hacer un guion de shell que entube el resultado de banner a un correo electronico de mail. Un buen prograam de shell le permitira enviar a un usuario distinto cada vez que se ejecute. El usuario deberia ser entonces una variable. Existen dos maneras de especificar una variable en un guion de shell.
- parametros posicionales
- variables que define usted mismo
Parametros posicionales
Un parametro posicional es una varibale que se encuentra en una
posicion especificada en la linea de comandos de su guion de shell. Los
parametros posicional se ingresan despues del comando. Son cadenas de
caracteres delimitadas por espaciones en blanco, excepto para el ultimo
parametro. Si el primer parametro posicional es pp1,
pp2 es el segundo parametro posicional, y ... pp9 es
el noveno parametro posicional, entonces la linea de comando de su guion
de shell shell.prog
tendra este aspecto:
$ shell.prog pp1 pp2 pp3 pp4 pp5 pp6 pp7 pp8 pp9
El guion de shell tomara el primer parametro posicional
(pp1
) y lo sustuitira en el texto del guion de shell por
los caracteres $1
. El segundo parametro posicional
pp2
sera sustituido por los caracteres $2
. El
noveno parametro posicional (pp9
), por supuesto, le
corresponde ser sustituido por los caracteres $9
.
Si desea ver como se sustituyen los parametros posicionales en un
programa, intente ingresar las siguientes lineas en un fichero llamado
pp
.
echo El primer parametro posicional es: $1
echo El segundo parametro posicional es: $2
echo El tercer parametro posicional es: $3
echo El cuarto parametro posicional es: $4
El primer comando echo le dice cual parametro aparecera en pantalla y luego mostrara el parametro.
Ahora le damos permisos de ejecucion al guion de shell
pp
y ordenamos su ejecucion para ver que sucede:
$ chmod u+x pp
$
$ pp uno dos tres cuatro
El primer parametro posicional es: uno
El segundo parametro posicional es: dos
El tercer parametro posicional es: tres
El cuarto parametro posicional es: cuatro
Si cambiamos los parametros posicionales previstos, estos cambiaran en el resultado:
$ pp River Boca cancha pelota
El primer parametro posicional es: River
El segundo parametro posicional es: Boca
El tercer parametro posicional es: cancha
El cuarto parametro posicional es: pelota
Sabiendo esto, ahora volvemos a vrear un guion de shell para el
cartelon cumpleanero. Lo llamamos cumple
. ¿Que lineas de
comandos ponemos en el fichero?
$ cat cumple
banner Feliz cumple! | mail $1
Intente mandarse un saludo de cumpleanos a usted mismo. Podria usar
$ cumple $USER
You have mail
$
El comando who le dice que usuarios estan usando actualmente
la computadora. ¿Como haria un guion de shell simple llamado
quienesta
que le diga si un login particular esta
trabajando actualmente en el sistema?
Intente lo siguiente:
$ who | grep jefe
jefe tty51 Nov 29 17:01
$
Este comando entuba la salida del comando who al comando
grep. El comando grep busca los caracteres "jefe". Como el
usaurio jefe
se enceuntra logueado al sismtea, la sehll le
responde con:
jefe tty51 Nov 29 17:01
Si la unica respuesta es un signo $
de prompt, entonces
el usuario jefe
no se encuentra conectado a la computadora
actualmente (ya que el comando grep no encontro nada. Cree el
guion de shell esta
.
Debajo tiene los ingredientes para su guion de shell
esta
:
who |
El comando de shell que lista a todos los conectados al sistema |
grep |
El comando que busca cadenas |
$1 |
El primer parametro posicional de su guion de shell |
El comando grep busca en la salida del comando who el
parametro designado en el programa como $1
. Si encuentra el
usuario, mostrara la linea de informacion. Si no encuentra el usaurio en
la salida provista por who, mostrara su prompt.
Edite un fichero llamado esta
con su editor favorito, e
ingresele el siguiente comando:
who | grep $1
Guarde el fichero esta
, salga del editor, y cambiele el
modo con chmod para darle permisos de ejecucion.
Ahora intente proporcionale a esta
un nombre de usaurio
como parametro posicional. ¿Cual es la respuesta de la computadora?
Si su nombre de usuario es mengano
, la respuesta de su
nuevo guion de shell podria ser:
$ esta mengano
mengano tty26 Ene 24 13:35
$
El primer parametro posicional es el nombre de usuario
mengano
. La shell sustituye el $1 de su programa por
mengano
, de esta manera:
who | grep mengano
La linea de comandos de la shell permite hasta 128 parametros
posicionales. Sin embargo, su guion de shell esta restringido desde $1 a
$9, a no ser que use el $*
que se describira a
continuacion, o el comando shift, que se describe en el
documento de Programacion de Comanods de Shell del Sistema UNIX.
Parametros con Significado Especial
$#
Esta variable de su guion de shell registrara y
mostrara el numero de los parametros posicionales que usted proveyo al
guion de shell.
Veamos un ejemplo que demuestre que sucede cuando usamos
$#
. Ingresemos el siguiente comntenido en un guion de shell
ejecutable llamado obt.num
.
echo El numero de parametros es: $#
Este programa contara todos los parametros posicionales habido y mostrara la cifra numerica. Puede ser cualquier cadena de caracteres.
$ obt.num La vuelta vamos a dar
En numero de parametros es: 5
$
Como vemos, obt.num cuenta y muestra la cantidad de argumentos.
$*
Esta variable de guion de shell sustituira todos los
parametros posicionales que comiencen con el primer parametro posicional
El parametro $*
no lo restringira a solamente nueve
parametros.
Puede hacer un guion de shell simple para demostrar la variable
$*
. Escriba un guion de shell ejecutable llamado
mostrar.param
que de eco de todos los parametros:
echo Los parametros para este comando son: $*
Al ejeceutarlo podria indicar:
$ mostrar.param Hola como estas
Los parametros para este comando son: Hola como estas
$
Ahora intente usar mostrar.param con mas de nueve parametros posicionales:
$ mostrar.param uno dos 3 4 5 seis 7 8 9 10 once
Los parametros para este comando son: uno dos 3 4 5 seis 7 8 9 10 once
$
La variable $*
es muy util si se usan generacion de
nombres de ficheros como parametros.
Intente un parametro de generacion de nombre para su comando
mostrar.param
, capaz de imprimir un listado de un
directorio, si este cuenta denominados cap1
,
cap2
, hasta cap7
con ficheros de texto que son
capitulos de un manual, obtendra un listado impreso de todos esos
capitulos.
$ mostrar.param cap?
Los parametros para este comando son: cap1 cap2 cap3 cap4 cap5 cap6 cap7
$
Podria querer practicarr con parametros posicionales de manera que le resulten familiares antes de continuar con la siguiente seccion en la cual nombrara las variables dentro de uin programa en lugar de usarlas como argumentos desde la linea de comandos.
Nombres de Variables
La shell le permite nombrar las variables dentro de un guion de shell. Al nombrar las variables en un guion de shell, esto hace mas simple que otra persona pueda usarlo. En lugar de usar parametros posicionales, le dira al usuario que ingresar en la variable, o le dara a dicha variable un valor que es la salida de un comando.
¿Que apariencia tiene una variable designada? En el ejemplo
siguiente, var1
es el nombre de la variable, y
minombre
es el valor o cadena de caracteres asignada a
dicha variable. No hay espacios que rodeen al signo =
:
var1=minombre
Dentro de la shell, un $
en frente al nombre de la
variable, alerta a la shell que debe realizar una sustitucion en el
guion de shell. $var1 le dice a la shell de sustituir el valor
minombre
, que fue dado a var1
, en la forma de
los caracteres $var1
.
El primer caracter de un nombre de variable deve ser una letra o un
guion bajo _
. El resto del nombre de la variable puede
componerse de letras a-z
, guiones bajos _
, y
digitos 0-9
. Como en el caso de los nombres de fichero de
programas de shell, es riesgoso tambien recurrir al nombre de un comando
de shell para usarlo como nombre de variable. Debe notar tambien que la
shell tiene algunos nombres de variables reservadas para el mismo. A
continuacion se dan los nombres de variables usadas por la shell, que no
deben emplearse para nombrar sus propias variables.
CDPATH |
Define la ruta de busquedas para el comando cd |
HOME |
Directorio home/ por defecto para el comando cd |
IFS |
Separadores de campo interno (normalmente espacio en blanco , tabulacion , y retorno de carro . |
MAIL |
Nombre del fichero que contiene su correo electronico |
PATH |
Ruta seguida para encontrar comandos |
PS1 |
Cadena de prompt primario ($ por defecto) |
PS2 |
Cadena de prompt secundario (> por defecto) |
TERM |
Modelo de terminal de trabajo. |
Muchas de estas variables nombradas se explican en la ultima seccion de este capitulo en su ambiente de usuario.
Asignar Valores a Variables
Si has editado con vi, sabe que debe establecer la variable
TERM
de modo que su valor sea el correspondiente a su
terminal antes de poder comenzar a trabajar en editor de pantalla. Por
ejemplo
TERM=VT100
Esta es la manera mas simple de asignar un valor a una variable.
Existen otras formas de hacerla. Una es usar el comando read
y asignar entrada a la variable. Otra forma es asignar la variable desde
la salida de un comando, usando apostrofos agudos ...
.
Una tercer manera seria asignar un parametro posicional a la
variable.
Asignar Valores con el comando read
Puede establecer su programa de forma que ingrese el comando, y luego que le solicite ingresar el valor para la variable. El comando read asigna la entrada a la variable espeficiada. La sintaxis general del comando read es:
read var
Los valores asignados por read a var
seran
sustituidos por $var
en el programa. Si se ejecuta el
programa echo justo antes del comando echo, el
programa puede mostrar las indicaciones 'Escriba...
. El
comando read esperara hasta que ingrese el valor, y luego
asignara la cadena de caracteres mecanografiada por usted como valor
para la variable.
Si tenia una lista que contenia los nombres y numeros telefonicos de la gente que llama a menudo, podria hacer un programa simple que automaticamente le de el nombre de alguien. ¡Un momento! ¿Como haria tal guion de shell con los siguientes ingredientes?
echo |
comando que de eco de instrucciones |
read |
comando que asigne valor de entrada a la variable nombre |
grep |
comando que busque el nombre de la persona y el numero |
Primero, usaria el comando echo para informar al usuario que mecanografia el nombre a llamar
echo Ingrese el apellido
El comando read entonces asignaria el nombre de la persona a
la variable name
read name
note que no usa el =
para asignar la variable; el
comando read la asigna automaticamente a los caracteres
introducidos en la varible nombre
.
El comando grep buscara entonces su lista telefonica en busca del nombre. Si la lista telefonica se llamara agenda, la linea de comandos seria
grep $nombre agenda
En el siguiente ejemplo, el guion de shell se llama tel
.
Recuerde, la respuesta de sistema al programa cat es los
contenidos del fichero del guion de shell.
$ cat tel
echo Ingrese el apellido
read nombre
grep $nombre agenda
$
Haga un listado de apellidos y numeros telefonicos llamado
agenda
y pruebe tel
. O, intente el siguiente
ejemplo, que es un programa que crea el listado en si. Puede usar varias
variables en un solo programa. Si tiene un listado telefonico, podria
querer contar con una manera rapida y sencilla de agregar nombres y
numeros telefonicos al mismo. Este programa:
- Asignaria el nombre de la persona,
- Asignaria el nombre a la variable
nombre
- Pide el numero de telefono de la persona,
- Solicita el numero a la variable
num
, y - da eco del
nombre
ynum
del ficheroagenda
. Debe usar>>
para redirigir la salida del comando echo al final de la lista. Si usa >, su lista contendra solo el ultimo numero telefonico.
El programa se llamara agendar
$ cat agendar
echo Ingrese el nombre
read nombre
echo Ingrese el numero telefonico
read num
echo $nombre $num >> agenda
$
$ chmod u+x agendar
$
Ahora pruebe los nuevos programas para su agenda telefonica. En el
siguiente ejemplo, usamos agendar
para crear un nuevo
listado para Sr. Fulano Sultano. en el fichero agenda
.
Luego, usamos tel
para saber el telefono del Sr.
Sultano.
$ agendar
Ingrese el nombre
Sr. Fulano Sultano
Ingrese el numero
5555-1234
$
$ tel
Ingrese el apellido
Sultano
Sr. Fulano Sultano 5555-1234
$
Vea que que la variable nombre
acepta tanto
Sr.
, Fulano
y Sultano
como su
valor.
Sustituir salida de comando por el Valor de una Variable
Otra forma de asignar un valor a una variable es sustituir la salida de un comando por el valor. Esto sera muy util en la siguiente seccion, donde intentaremos bucles y construcciones condicionales.
La sintaxis general para asignar una salida como valor de variable es recurrir al apostrofe agudo ```:
var=`comando`
La variable var
tendra el valor de la salida de
comando
.
En uno de los ejemplos anteriores de entubado, redirigimos el comando date al comando cut para obtener la hora correcta. Dicha linea habia sido
date | cut -c12-19
Puede colocar dicho comando en un programa de shell llamado
hora
que nos de la hora.
$ cat hora
hora=`date | cut -c12-19`
echo Son las $hora
$
Recuerda que aqu{i no hay espacioes en blanco a los costados del
signo =
.
Cambia el modo del fichero y ahora tendras un microprograma que te da la hora.
$ chmod u+x hora
$ hora
Son las 10:36
$
Asignar Valores con Parametros Posicionales
Puede asignar un parametro posicional como parametro designado. Por ejemplo:
var1=$1
El ejemplo siguiente es un guion de shell simple simp.p
que demuestra como puede asignar un parametro posicional dado a una
variable. Las lineas de comandos de tal guion serian las siguientes:
$ cat simp.p
var1=$1
echo $var1
$
O, puede asignar la salida de un comando que usa un parametro posicional:
persona=`who | grep $1`
Si quiere mantener registro de su programa esta
, podria
crear un programa picaentrada
. La salida de su guion de
shell esta
se asignara a la variable persona
.
Luego, el valor de $persona
se agregara al finchero
lista.ingreso
con el comando echo,. La ultima
parte del programa mostrara el valor de $persona
, que es el
mismo que la respuesta al comando esta
.
$ cat picaentrada
persona=`who | grep $1`
echo $persona >> lista.ingreso
echo $persona
$
La respuesta de la computadora a picaentrada
aparecera
de la siguiente manera:
$ picanetrada fulana
fulana tty61 Abr 11 10:26
$
En la medida que programe mas cosas, descubrira otras maneras de asignar variables que le ayudaran a hacer mejores microprogramas por medio de los guiones de shell.
Construcciones de Programacion de Guiones
El lenguaje de programacion de la shell cuenta con varias construcciones que le permiten programar con mayor flexibilidad.
-
El "aqui documento" le permite redirigir lineas de entrada a un comando.
-
La construccion de bucle for y while hacen que un programa reitere comandos en bucle.
-
Los comandos de control condicional if y case ejecutan un grupo de comandos solo si un conjunto de condiciones particulares se cumplen.
-
El comando break le ofrece una finalizacion incondicional al bucle.
Comentarios
Antes de comenzar a escribir programas de la shell con bucles, querra
sabner como poner comentarios sobre su programa en el mismo fichero, los
cuales son ignorados por el sistema. Para poner comandos en un programa,
comience el comentario con #
y terminelos con tecla
Intro. La sintaxis general para comentar una linea es:
#comentario
La shell ignorara todos los caracteres que sigan al #
.
Estas lineas
#Este programa envia un saludo de cumpleanos generico
#Este programa necesita un usuario como parametro posicional.
sera ignorado por el sistema cuando su programa se ejecuta. Simplemente sirve como un recordatorio para ti, el programador.
El Documento Aqui
El Documento Aqui
le permite redirigir lineas de entrada
incluidas en un programa de shell a un comando. El documento shell
consiste en el simbolo de redireccion <<
y un
delimitador que especifica tanto el comienzo como el final de
las lineas de entrada. El delimitador puede ser un caracter o una cadena
de caracteres. A menudo se define como delimitador el caracter
!
. La sintaxis general del documento Aqui
es:
comando <<!
...lineas de entrada...
!
El documento Aqui
puede usarse en un programa de shell
que redirija las lineas de entrada al comando mail. El
programa fcumple
indicado a continuacion envia un saludo
generico de cumpleanos con el comando mail.
$ cat fcumple
mail $1 <<!
Que los cumplas muy feliz!
!
El parametro posicional $1
debe ser el nombre de usuario
del destinatario.
La entrada redirigida a mail sera
Que los cumplas muy feliz!
Para enviar el saludo:
$ fcumple maria
$
Para recibir esta salutacion, la usuaria maria ejecutaria el comando mail
$ mail
De fulana Lun May 14 14:31 CDT 1984
Que los cumplas muy feliz!
$
Usar ed en un programa de shell
El editor de lineas ed puede usarse dentro de un programa de shell, si se combina con los comandos del documento Aqui.
Suponga que desea hacer un programa de shell que ingrese al editor ed, realice una sustitucion global a un fichero, escriba el fichero, y luego salga del editor. El comando de ed que realiza una sustitucion global es:
g/texto a cambiar/s//texto de reemplazo/g
Antes de continuar leyendo, piense bien cual cree que sera la
secuencia del comando. Ponga su secuencia de comandos en un fichero
llamado cambio.text
. Si desea suprimir el conteo de
caracteres de ed de modo que no aparezcan en su
terminal, use la opcion -
:
ed - fichero
Intente ejecutar el fichero. ¿Funciona?
Si uso el comando read para ingresar las variables,
su programa cambio.text
podria parecer similar al que
aparece a continuacion:
$ cat cambio.text
echo Ingrese un nombre de fichero
read fichero1
echo Ingrese el texto exacto a cambiar.
read busqueda
echo Ingrese exactamente el nuevo texto con el cual reemplazar al anterior.
read reemplazo
ed - $fichero1 <<!
g/$busqueda/s//$reemplazo/g
w
q
!
$
Este programa usa tres variables. Cada una de ellas se ingresa al programa con el comando read.
$fichero
es el nombre del fichero a editar.$busqueda
es el texto exacto que se quiere cambiar.$reemplazo
es el texto nuevo.
Una vez que las variables son introducidas al programa, el documento aqui redirige los comandos busqueda global, grabar, y salir al editor ed.
Pruebemos el nuevo comando cambios.text
:
$ cambio.text
Ingrese un nombre de fichero
carta.txt
Ingrese el texto exacto a cambiar.
Estimado Juan
Ingrese exactamente el nuevo texto con el cual reemplazar al anterior.
A quien pueda concernir
cat carta.txt
Calle de los Pinos 1234
Santa Eduviges, Molinos
A quien pueda concernir:
Hemos notado que en la publicacion del dia 23 de mayo, se refirio a...
(...)
¿Intento utilizar parametros posicionales? ¿Tuvo problemas al ingresar los cambios de texto como variables, o cito la cadena de caracteres para cada parametro?
Tambien puede usarse el editor de flujos sed en la programacion de shell.
Bucles
Hasta ahora, los comandos en su programa de la shell han sido ejecutados una vez, y solo una vez, y secuencialmente. La construccion bucle le ofrece la ejecucion repetitiva (iterada) de un comando o grupo de comandos. Los comandos for y while haran que el programa haga bucles y ejecute una secuencia de comandos en varias ocasiones.
El bucle for
El bucle for
ejecuta una secuencia de comandos para cada
miembro de la lista. El bucle de comando for
requiere las
palabras clave in
, do
y done
. Las
palabras clave for
, do
, y done
deben ser la primer palabra en la linea. La sintaxis general para
el bucle for es:
for variable
in esta lista de valores
do los siguientes comandos
comando1
comando2
.
.
.
ultimo comando
done
La variable puede ser cualquier nombre que elijamos. Si es
var
, entonces los valores dados despues de la palabra clave
in
seran sustituidos secuencialmente por $var
en la lista de comandos. Si se omite in
, los valores para
var
seran los parametros posicionales. La lista de comandos
entre las palabras clave do
y done
seran
ejecutados para cada valor.
Cuando los comandos se ejecutaron hasta el ultimo valor, el programa
ejecutara la siguiente linea que siga a done
. Si no hay
ninguna linea por debajo, el programa finaliza.
Es mas sencillo leer un programa de shell si la construccion de bucle
se resalta. Ya que la shell ignora los espacios al comienzo de la linea,
se usa indentar cada seccion de comandos como aparece en la sintaxis
anterior. Tambien, si indenta cada seccion de comandos, podra observar
rapidaemten para asegurarse que cada do
tiene un
done
correspondiente al final del bucle, que le de
cierre.
La manera mas facil de entender una construccion de programacion de shell es intentar un ejemplo. Intente crear un programa que mueva ficheros a otro directorio.
Los ingredientes para este programa seran:
- echo: quiere que de eco de instrucciones para que usted ingrese una ruta de cada directorio nuevo.
- read: quiere ingresar el nombre de ruta, y
asignarlo a la variable
ruta
. - for
variable
: Debe nombrar la variable. Llamelafichero
en su programa de shell. Aparecera como$fichero
en la secuencia de comandos. - in
secuencia de comandos
: la secuencia de comandos para este programa sera:mv $fichero $ruta/$fichero
- done
El contenido de programacion de su programa de shell mv.fichero podria ser:
$ cat mv.fichero
echo Por favor indique la ruta de directorio
read ruta
for fichero
in carta1 carta2 carta3
do
mv $fichero $ruta/$fichero
done
Tenga presente que no ingreso ningunos valores para la variable
fichero
; los valores ya estan programados inflexiblemente.
Si quesea cambiar los ficheros cada vez que invoca el programa, use
parametros posicionales o bien variables que usted nombre. No necesita
la palabra clave in
para listar los valores al usar
parametros posicionales. Si escoge usar parametros posicionales, su
programa sera mas flexible, y tendra esta apariencia.
$ cat mv.fichero
echo Por favor indique la ruta de directorio
read ruta
for fichero
do
mv $fichero $ruta/$fichero
done
Es probable que quiera mover varios fichero usando los varios metacaracteres de generacion de nombre de fichero, que hemos visto.
El bucle While
El bucle while continuara ejecutando la secuencia de
comandos en la lista do...done
en tanto el comando final de
la lista de comando de while devuelva un status de
verdadero (true
), o sea que puede ser ejecutado. Las
palabras clave while
do
y done
deben ser los primeros caracteres de la linea. La sintaxis general del
bucle while es el siguiente:
while
comando1
.
.
.
ultimo comando
do
comando1
.
.
.
ultimo comando
done
Estas son las lineas de un programa simple llamado
ingresa.nombre
que usa el bucle while para
introducir una lista de nombres en un fichero:
$ cat ingresa.nombre
while
read x
do
echo $x >> ficherox
done
$
Este programa de shell necesita algunas instrucciones. Debe saber que
para delimitar o separar los nombres tiene que usarse la tecla
Intro, y que tiene que usar Ctrl+d para
finalizar el programa. Tambien seria amable si su programa mostrara la
lista de nombres de xfichero
al finalizar el programa. Si
le agregamos estos ingredientes al programa, cobraria la siguiente
apariencia:
$ cat ingresa.nombre
echo 'Por favor ingrese cada nombre personal, y luego presione la tecla Intro.'
echo 'Por favor, finalice el ingreso de nombres con Ctrl+d.'
while read x
do
echo $x >> ficherox
done
echo ficherox contiene los siguientes nombres:
cat ficherox
$
Note que una vez que se complete el bucle, el programa ejecutara el
comando que viene despues de done
.
En la linea del comando echo
, usted ha utilizado
metacaracteres que son especiales para la shell, de modo que se debe
recurrir a usar '...'
para desactivar dicho significado
especial. Colocamos todos las lineas de comando anterior en un fichero
ejecutable y lo evaluamos como programa de shell.
Por favor ingrese cada nombre personal, y luego presione la tecla Intro.
Maria Luisa
Jana
^d
ficherox contiene los siguientes nombres:
Maria Luisa
Jana
Construcciones condicionales if...then
El comando if le dice al programa de shell que
ejecute la secuencia then de comandos solo si el
comando final de la lista de comandos if ha sido
exitoso. La construccion if finaliza con la palabra
clave fi
. La sintaxis general de la construccion
condicioinal if es la siguiente:
if
comando1
.
.
.
ultimo comando
then
comando1
.
.
.
ultimo comando
fi
El siguiente programa de shell demuestra la construccion
if...then. El programa buscara una palabra en un
fichero. Si el comando grep tiene exito, entonces el
programa usara echo para mostrar dicha palabra
encontrada en el fichero. En este ejemplo, las variables se leen en el
programa de shell. Ingrese el programa a continuacion y pruebelo. Llame
al programa buscar
.
$ cat buscar
echo Ingrese la palabra y el nombre de fichero
read palabra fichero
if grep $palabra $fichero
then echo $palabra esta en $fichero
fi
$
Note que el comando read esta asignando valores a
dos variables. Los primeros caracteres que usted ingrese, hasta el
espacio en blanco, son asignados a la variable palabr
,
mientras que todos los caracteres restantes (incluyendo espacios en
blanco) seran asignados a la siguiente variable
fichero
.
Escoja una palabra que sabe que existe en un fichero, y evalue este programa de shell. ¿Se da cuenta que a pesar de que el programa funciona, existe un problema irritante? Su programa muestra mas de la lines de texto descubiertas. Las lineas de texto extra mostradas en su terminal son la salida del comando grep.
El cesto de la shell /dev/null
La shell cuenta con un fichero que actua de cesto de basura. Puede
depositar cualquier salida no deseada en el fichero
/dev/null
, redirigiendo la salida alli.
Probemos el "cesto de basura" tirando alli los resultados del comando
who. Primero, ingrese el comando who. La respuesta le
dira quien esta logueado en el sistema. Ahora, intente el comando
who, pero redirija la salida al fichero
/dev/null
:
who > /dev/null
La respuesta que aparecera en su terminal sera el prompt. La
respuesta del comando who sera descartada a
/dev/null
y se convertira en nula, en la nada misma. Si
desea disponer de la respuesta del comando grep de su
cumando buscar
tirandola a la basura en lugar de mostrarla,
modifique la linea del comando if
para que quede asi:
if grep $palabra $fichero > /dev/null
Ahora ejecute el programa buscar
. Este deberia responder
solo con el texto del comando de la linea echo
.
La construccion if...then tambien puede ofrecer un
conjunto de comandos alternativo con else
, que actuara en
caso que la secuencia de comandos if
sea falsa. La sintaxis
general de la construccion if...then...else es la
siguiente:
if
comando1
.
.
.
ultimo comando
then
comando1
.
.
.
ultimo comando
else
comando1
.
.
.
ultimo comando
fi
Ahora podremos mejorar el comando buscar
. Este programa
por ahora busca una palabra en un fichero. Si encuentra la palabra, el
programa le dira que la palabra se encontro. Si no la encuentra
(else
) el programa le dira que la palabra NO fue
encontrada. El codigo del fichero buscar
ahora sera el
siguiente:
$ cat buscar
echo Ingrese una palbra y el nombre de fichero
read palabra fichero
if
grep $palabra $fichero > /dev/null
then
echo $palabra esta en $fichero
else
echo $palabra NO ESTA en $fichero
fi
Comando test para bucles
test es un comando muy util en las
construcciones condicionales. El comando test
revisa si ciertas condiciones son verdaderas. Si la condicion es
verdadera, entonces el bucle continuara. Si la condicion es falsa,
entonces el bucle finaliza y se ejecuta el siguiente comando. Algunas de
las opciones utiles del comando test
son:
test -r fichero | Verdadero si existe y es legible |
test -w fichero | Verdadero si el fichero existe y tiene permisos de escritura |
test -x fichero | Verdadero si el fichero existe y es ejecutable |
test -s fichero | Verdadero si el fichero existe y tiene al menos un caracter |
Si no ha cambiado los valores de su varaible PATH
que le
dio incialmente el sistema, entonces los ficheros ejecutables en su
directorio /bin
pueden ser ejecutados desde cualquiera de
sus directorios. Podria querer crear un programa de shell que mueva
todos los ficheros ejecutables del directorios actual a su directorio
/bin
. El comando test -x
puede usarse para
seleccionar los ficheros ejecutables desde una lista de ficheros en el
directorio actual. Revise el ejemplo de la construccion for
del programa mv.fichero:
$ cat mv.fichero
echo Por favor indique la ruta de directorio
read ruta
for fichero
do
mv $fichero $ruta/$fichero
done
Incluya una declaracion if test -x
en el bucle
do...done para mover solo aquellos ficheros que
son ejecutables.
Si nombra al programa mv.exe
, el programa de shell
podria tener la siguiente apariencia:
$ cat mv.exe
echo Por favor indique la ruta de directorio
read ruta
for fichero
do
if test -x $fichero
then
mv $fichero $ruta/$fichero
fi
done
$
La ruta de directorio sera la ruta desde su directorio actual al
directorio /bin
. Sin embargo, si usar el valor para la
variable de interprete HOME
, no necesitara ingresar la ruta
cada vez. $HOME
le da la ruta de su directorio de login.
$HOME/bin
le da la ruta a su directorio /bin
de usuario.
$ cat mv.exe
for fichero
do
if test -x $fichero
then
mv $fichero $HOME/bin/$fichero
fi
done
$
Para ejecutar el comando, use como parametro posicional a todos los
ficheros del directorio actual, con *
. La siguiente ejecuta
el comando desde el directorio actual y luego mueve al directorio /bin
de usaurio y lista los ficheros que quedaron alli. Deberian estar todos
los ficheros ejecutables.
$ mv.exe
$ cd; cd bin; ls
La construccion condicional case...esac
La case..esac es una construccion multiple choice,
que permite elegir una de varios patrones, y luego ejecutar una lista de
comandos para dicho patron. La palabra clave in
debe
comenzar las declaraciones de patron con su secuencia de comandos. Debe
cerrar cada patron con un caracter de )
. La secuencia de
comandos para cada patron se finaliza con ;;
. La
construccion case
debe cerrarse con esac
(las
letras de case
invertidas). La sintaxis general para la
construccion case es:
case caracteres
in
patron1
linea de comando1
.
.
.
ultima linea de comando
;;
patron2)
linea de comando1
.
.
.
ultima linea de comando
;;
esac
La construccion case intentara coincidir caracteres
con el primer patron. Si hay coincidencia, el programa ejecutara las
lineas de comando para el primer patron hasta llegar a la
;;
.
Si el primer patron no coincide, entonces el programa procedera al
segundo patron. Luego de alcanzar una coincidencia de patron, el
prorgrama no intentara coincidir ningun otro patron mas, pero ira al
comando que sigue a esac
. el *
usado como
patron al final de la lista de patrones le permite dar instrucciones a
realizar si ninguno de los patrones tuvo coincidencias. El
*
significa "cualquier patron", por lo que debe colocarse
al final de la lista de patrones si es que antes deben revisarse
otros patrones de cualquier tipo.
Si usted ha usado el editor vi, ya sabe que
debe asignar un valor a la variable TERM
para que la shell
conozca que tipo de terminal utiliza para usar las funciones de edicion
de pantalla de vi. Un buen ejemplo de la construccion
case seria un programa que establece la variable
TERM
por usted de acuerdo al tipo de terminal que utiliza
para loguearse. De este modo, si se loguea con diferentes tipos de
terminales, el programa set.term
le sera muy util.
set.term
le pedira que ingrese el modelo de terminal, y
luego configurara la variable de terminal segun el codigo de terminal.
Las lineas del mismo son:
TERM=codigo de terminal
export TERM
En este ejemplo de set.term
la persona usa tanto un
TELETYPE 4420, TELETYPE 5410 o un TELETYPE 5420.
El programa set.term
revisara primero si el valor de
term
es vt52
. Si lo es, entonces asignara el
valor VT52
a TERM
, y saldra del programa. Si
no es vt52
, revisara si es vt100
y luego
vt320
. Comenzara a ejecutar los comandos bajo el primer
patron que encuentre, y luego pasara al siguiente comando luego de
esac
.
Al final de los patrones para las terminales de la serie VT aparece el patron *
que
significa todo lo demas, le advertira que no tiene un patron para esa
terminal, y le permitira abandonar la construccion
case.
echo Si tiene una terminal DEC VT52, ingrese vt52
echo Si tiene un terminal DEC VT100, ingrese vt100
echo Si tiene un terminal DEC VT320, ingrese vt320
read term
case $term
in
vt52)
TERM=VT32
;;
vt100)
TERM=VT100
;;
vt320)
TERM=VT320
;;
*)
echo No es un tipo de terminal correcto.
;;
esac
export TERM
echo Fin del programa
¿Que hubiese sucedido de haber puesto el patron *
al
principio? el programa set.term
nunca hubiese asignado un
valor a TERM
ya que siempre hubiese coincidido con el
primer patron *
, que significa "todo".
Cuando lee la seccion de modificar su ambiente de inicio de sesion,
podria querer aprovechar el programa set.term
en su
directorio /bin
, y agregar la linea de comandos:
set.term
a su fichero ~/.profile
.
Declaracion de control incondicional break
El comando break detiene incondicionalmente la
ejecucion de cualquier bucle en el cual se encuentra, y va al siguiente
comando que sigue a las declaraciones done
,
fi
, o esac
. Si no hay comandos luego de dicha
declaracion, el programa finaliza.
En el ejemplo del programa set.term
, el comando
break podria haberse utilizado en lugar del comando
echo.
echo Si tiene una terminal DEC VT52, ingrese vt52
echo Si tiene un terminal DEC VT100, ingrese vt100
echo Si tiene un terminal DEC VT320, ingrese vt320
read term
case $term
in
vt52)
TERM=VT32
;;
vt100)
TERM=VT100
;;
vt320)
TERM=VT320
;;
*)
break
;;
esac
export TERM
echo Fin del programa
En la medida que escriba mas programas de shell, podria querer usar dos otros comandos incondicionales, el comando continue y el comando exit. El comando continue hace que el programa vaya inmediatamente a la siguiente iteracion de un bucle do o for, sin ejecutar los siguientes comandos que quedan en el bucle.
Normalmente, un programa de shell termina al alcanzarse el final del fichero. Si desea que el programa finalice en cualquier otro momento, puede usar el comando exit.
Depurando programas
Depurar es un termino informatico que significa buscar y encontrar errores en un programa. Existiran veces en las cuales ejecute un programa de shell y no pasara nada. Hay un "bug" en su programa.
Su programa puede consistir en varios pasos, o varios gurpos de comandos. ¿Como descubriria cual paso es el culpable? Existen dos opciones en el interprete sh que lo ayudaran a depurar un programa.
sh -v |
Presenta las lineas de ientrada de la shell en la medida que son leidas por el sistema |
sh -x |
Presenta los comandos y sus argumentos en la medida que se ejecutan |
Para intentar estas dos opciones, cree un programa de shell que
contenga un error en el. Por ejemplo, ingrese la siguiente lista de
comandos en un fichero llamado bug
.
$ cat bug
hoy='date'
persona=$1
mail $2
$persona
Cuando se desconecte, venga a mi oficina, por favor.
$hoy
MLH
$
El mensaje de correo enviado a Tomas ($1
) con el login
tomi ($2
) debe leerse como se muestra en la
siguiente pantalla.
De mlh Mie Abr 10 11:36 CST 1984
Tom
Cuando se desconecte, venta a mi oficina por favor.
Mie Abr 10 11:36:32 CST 1984
MLH
$
?
.
Si intenta ejecutar bug
, tendra que presionar la tecla
BREAK o la tecla Del para finalizar el programa.
Para depurar este programa, intente sh -v
, que
presentara las lineas del fichero en la medida que son interpretadas por
la shell.
$ sh -v bug tomas tomi
hoy='date'
persona=$1
mail $2
Note que la salida se detiene en el comando mail. Hay problemas con mail. El documento aqui debe usarse para redirigir la entrada a mail.
Antes de corregir el programa bug
, probemos con
sh -x
, que nos imprime los comandos y sus argumentos en la
medida que son leidos por la shell.
sh -x bug tomas tomi
+date
hoy=Mie Abr 10 11:07:23 CST 1984
persona=tomas
+mail tomi
Una vez mas, el programa se detiene en el comando mail. Note que las sustituciones para las variables han sido establecidas, y se presentan.
El programa bug
corregido es el siguiente:
$ cat bug
hoy='date'
persona=$1
mail $2 <<!
$persona
Cuando se desconecte, venga a mi oficina por favor.
$hoy
MLH
!
$
El comando tee es un comando util para depurar canerias. Coloca una copia de la salida de un comando en un fichero que usted nombre, asi como lo entuba a otro comando. La sintaxis general del comando tee es:
comando1 | tee fichero.guardado | comando2
fichero.guardado
es el nombre del fichero en el que
desea guardar la salida de comando1, para su
conservacion y/o estudio.
Si queire revisar la salida del comando grep en la siguiente linea de comandos:
who | grep $1 | cut -c1-9
Puede usar tee para copiar la salida de grep en un fichero para revisarlo una vez que el programa haya terminado con su ejecucion.
who | grep $1 | tee revisar | cut -c1-9
el fichero revisar
contiene una copia de la salida del
comando grep
$ who | grep mlhmo | tee revisar | cut -c1-9
$ mlhmo
$ cat revisar
mlhmo tty61 Abr 10 11:30
$
Si escribe muchos programas de shell, querras referirte a UNIX System Shell Commands and Programming, y aprender sobre los codigos de retorno de los comandos, y redirigir la salida de error estandar.
Modificando su Ambiente de Logueo
¿Que es un .profile?
Agregar comandos a .profile
Configurar las opciones de TErminal
Usar variables de shell
HOME
PATH
TERM
PS1
Una de las cosas interesantes de su .profile
es que
puedes cambiar el prompt. Esto es divertido para experimentar.
Prueba el siguiente ejemplo. Si deseas usar varias palabras, recuerda de
citar la frase entre comillas. Tambien su usas comillas puedes agregar
un retorno de carro a tu prompt.
Ingresa:
PS1="Sus deseos son ordenes<Tecla Intro>"
Y su prompt tendra el siguiente aspecto:
$ . .profile
Sus deseos son ordenes
El mundano $
desaparecio, al menos hasta que borre la
variable PS1
de su .profile
.
Conclusion
Este tutorial le ha otorgado lo basico para crear algunos guiones de programacion de shell. Si ha iniciado sesion y ha intentado los ejemplos y ejercicios de este tutorial, proablemente podras realizar muchas de tus tares diarias recurriendo a programas de shell. La programacion de shell puede ser mucho mas compleja y desarrollar tareas mas complicadas que las que se muestran aqui. Si quieres leer mas de los comandos de la shell y la programacion, lee el Manual de Referencia del Usuario del Sistema UNIX en lo que refiere al comando sh, el Comandos y Programacion del la Shell del Sistema UNIX o bien las manpages.