Next: Configuración
Up: Manejo
Previous: Manejo de Linux en
  Contents
Subsections
Con script (escrito) se denomina programas que se escriben en texto
claro y que son interpretados directamente, o sea, que no tienen que
pasar por un proceso de traducción. En otros ambientes se llaman también
archivos batch. Los lenguajes script se distinguen en el sentido,
que ellos mismos solo tienen la funcionalidad de aglutinar comandos
``externos'', los cuales pueden ser entonces de una complejidad
arbitraria, sin que el lenguaje script mismo tenga muchos comandos.
Existe un sinnúmero de lenguajes script, algunos ejemplos son Tcl,
perl y la gran variedad de shell's (interpretadores de comandos) como
son zsh, csh, ksh, sh. El shell estándard del proyecto GNU y de Linux
es bash e incorpora un lenguaje script muy poderoso.
Podemos ver un script como una listas de comandos que el sistema linux
permite ejecutar automáticamente, en vez de tener que introducirlos
manualmente. Hay tres conceptos que se asocian con los lenguajes script,
o la programación shell: la creación de ``macros'', o sea subsumir
bajo un solo nuevo nombre de comando una seríe de commandos indivduales,
la realización de tareas complejas a través de la combinación de varias
tareas sencillas - divide and conquer, y la realización de tareas
diferentes pero parecidas con un solo comando - parámetros.
Para crear un script se anotan los comandos individuales en secuencia
en un archivo ascii, el cual se puede interpretar a continuación,
utilizando el nombre del archivo como comando shell. Para esto se
le necesita dar permiso de ejecución al archivo, ej. (``macro''):
Escriba en un archivo de nombre 'archivos' la línea: ``ls'', ejecute
el commando: ``chmod +x archivos'', y a continuación ``./archivos''
El comando 'ls' se ejecutara.
Vamos a ver este proceso más detallado:
- Bash reconoce, que ``./archivos'' no es un comando interno.
- Normalmente busca en la via de acceso (Variable PATH) si encuentra
el archivo. En este caso, el nombre del archivo está especificado
absolutamente ('./' es el directorio actual, y 'archivos' existe)
entonces lo trata de ejecutar.
- El atributo de ejecución está activado entonces se determina si el
archivo es en uno de los formatos binarios que se pueden ejecutar
directamente. En este caso es un archivo de texto, no 'binario'
- Si la primera línea tiene la secuencia ``#!'' seguido por el
nombre de un comando (filtro), este comando se ejecuta, usando el
archivo script como entrada en stdin.
- En nuestro caso no existe esta línea, por lo que se ejecuta el shell
por omisión (default shell) como filtro.
- Este nuevo bash (sub-shell) lee la línea 'ls', y lo interpreta como
si hubieramos typeado el comando a mano: Se ejecuta 'ls' y los archivos
del directorio actual se alistan en la pantalla.
- El nuevo bash termina y regresamos al prompt del bash originador.
- #
- inicia un comentario, el resto de la línea se ignora
- $
- inicia una sustitución de variable
seguido por un número 0 - 9 reproduce en su lugar el texto del 'token'
0 - 9 respectivamente en la línea de commando
seguido por un texto reproduce el contenido de una variable shell
seguido por una expresión reproduce el texto del stdout de la expresión,
ejecutandola en un sub-shell.
- \
- preserva el siguiente carácter si este es especial,
o introduce caracteres especiales, \\
se convierte en \, se llama ``escape caracter''.
- \n
- nueva línea (newline) ; '\\n'
se convierte en '\n'
- \r
- retorno al inicio de la línea
- \t
- tabulador
- \g
- suena el timbre del terminal
- '
- (quote, single quote), protege una secuencia de caracteres y palabras
del procesamiento de línea de bash; 'au\nque no' se
mantiene intacto, inclusive '\n'
- ``
- (double-quote) igual como el single quote, pero ``\''
y ``$'' y ' preservan su función, ``\'' solamente
si es seguido por $, `, ", \, or <newline>.
- .StandardVariables
- bash, son nombres que pueden tener asignados
cadenas de caracteres arbitrarios. Comunmente se utilizan letras mayusculas,
para mas fácil diferenciarlos de los comandos.
Variables pueden ser leídos y escritos en cualquier momento. La preconfiguración
de la computadora asigna un juego completo a diferentes variables
tradicionalmente usados en unix. El juego de este variables permite
detectar desde los programas y comandos en que estado y con que usuario
etc. se encuentra el sistema en cualquier instanto. Porque definen
el ambiente de ejecución las variables también se llaman ``variables
de ambiente'' o ``ambiente'' (Environment variables, Environment).
El comando interno de bash 'set' escribe en stdout todas las variables
de ambiente y su valor. Para definir una variable simplemente se le
asigna un valor:
-
- VARIABLE=''Vamos a la playa''
Las variables solamente son válidos para su ambiente. Si se ejecuta
un sub-shell ya no son ``visibles''. Ej: ``echo $VARIABLE''
no imprime nada en stdout. Para hacer válida una variable se tiene
que ``exportar''; después de definir la variable se da el comando:
``export nombre'' con el nombre de la variable. De esta manera
se pueden crear jerarquías de validéz de variables (scope). Las variables
que solo los usamos temporalmente son ``protegidos'' de modificaciones
de sub-shells.
Bash ofrece una sintaxis simplificada: ``export CAJA=523'' es
lo mismo como: ``CAJA=523; export CAJA'', sin embargo se prefiere
utilizar la versión original en archivos script, para no crear incompatibilidad
con 'sh'.
La vida real nos exige tomarlas. Bash incluye comandos, que nos permiten
- Bifurcar
- Iterar
Estos dos elementos se conocen como control de secuencias. La bifurcación
se escribe de la siguiente manera:
-
- if TEST-COMMANDS; then
CONSEQUENT-COMMANDS;
[elif MORE-TEST-COMMANDS; then
MORE-CONSEQUENTS;]
[else
ALTERNATE-CONSEQUENTS;]
fi
Más especial:
-
- if [ algunos comandos ]; then
lista de acciones
else
otra lista
fi
El código de salida (exit status) del último comando de 'algunos comandos'
significa 'no válido' si es 0, en todos otros casos significa 'válido'.
Cada comando (inclusive los script) returna un valor numérico de salida
al shell que ejecuta. En el caso más simple el shell retorna 0 si
el comando se ha encontrado, otro valor en caso que no. Todos los
comandos y las funciones shell describen minuciosamente como se genera
su exit status, de donde se puede deducir como utilizarlos para la
bifurcación. El exit status del últio comando se tiene disponible
en texto mediante la variable especial $?.
La iteración se escribe de la siguiente manera:
-
- for VAR [in WORDS ...];
do COMMANDS;
done
donde VAR es una variable shell creada en el acto, que se asigna en
torno a cada cadena de caracteres presente en WORDS. si se omita se
sustituye por $@, los parametros posicionales.
Veamos algunos ejemplos reales, que nos pueden servir como machotes en caso de tener que resolver
una tarea parecida:
Para leer archivos ``HOWTO'' comprimidos:
-
- #!/bin/sh
if [ ''$1'' = '' ]; then
ls /usr/doc/faq/howto | less
else
gunzip -c /usr/doc/faq/howto/$1-HOWTO.gz | less
fi
Remover recursivamente archivos temporales y de respaldo de diferentes
aplicaciones conocidas y comprimir ciertos tipos de archivos:
-
- #!/bin/sh
#SQUEEZE removes unnecessary files and compresses .tex and README files
#By Barry tolnas, tolnas@sun1.engr.utk.edu
# echo squeezing $PWD
find $PWD \( -name \* -or -name \*.o -or -name \*.log -or -name \*\#\) -exec rm -f {} \;
find $PWD \( -name \*.tex -or -name \*README\* -or -name \*readme\* \) -exec gzip -9 {} \;
Convertir nombres de archivos a menusculas:
-
- for i in * ; do [ -f $i ] && mv -i $i `echo $i | tr '[A-Z]' '[a-z]'`; done;
Un script que hace lo mismo:
-
- #!/bin/sh
# lowerit
# convert all file names in the current directory to lower case
# only operates on plain files-does not change the name of directories
# will ask for verification before overwriting an existing file
for x in `ls`
do
if [ ! -f $x ]; then
continue
fi
lc=`echo $x | tr '[A-Z]' '[a-z]'`
if [ $lc != $x ]; then
mv -i $x $lc
fi
done
Remover archivos core:
-
- #!/bin/sh
USAGE=''$0 <directory> <message-file>''
if [ $# != 2 ] ; then
echo $USAGE exit
fi
echo Deleting...
find $1 -name core -atime 7 -print -exec rm {} \;
echo e-mailing
for name in `find $1 -name core -exec ls -l {} \; | cut -c16-24`
do
echo $name cat $2 | mail $name
done
Next: Configuración
Up: Manejo
Previous: Manejo de Linux en
  Contents
Georg Lehner
2003-10-28