www.ac.usc.es/docencia/ASRI/Tema_3html/node34.html
$ chmod +x helloworld
./helloworld
$ bash helloworld
$ . helloworldo bien:
$ source helloworld
Variable | Uso |
$0 | el nombre del script |
$1 a $9 | parámetros del 1 al 9 |
${10}, ${11},... | parámetros por encima del 10 |
$# | número de parámetros |
$*, $@ | todos los parámetros |
$ cat parms1.sh
#!/bin/bash
VAL=$((${1:-0} + ${2:-0} + ${3:-0}))
echo $VAL
$ bash parms1.sh 2 3 5
10
$ bash parms1.sh 2 3
5
El comando shift desplaza los parámetros hacia la izquierda el número de posiciones indicado:
$ cat parms2.sh
#!/bin/bash
echo $#
echo $*
echo "$1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}"
shift 9
echo $1 $2 $3
echo $#
echo $*
$ bash parms2.sh a b c d e f g h i j k l
12
a b c d e f g h i j k l
a b c d e f g h i j k
j k l
3
j k l
#!/bin/bashSi queremos leer o escribir a un fichero utilizamos redirecciones:
echo -n "Introduce algo: "
read x
echo "Has escrito $x"
echo -n "Escribe 2 palabras: "
read x y
echo "Primera palabra $x; Segunda palabra $y"
echo $X > ficheroEste último caso lee la primera línea de fichero y la guarda en la variable X
read X < fichero
#!/bin/bash
# FILE: linelist
# Usar: linelist filein fileout
# Lee el fichero pasado en filein y
# lo salva en fileout con las lineas numeradas
count=0
while read BUFFER
do
count=$((++count))
echo "$count $BUFFER"» $2
done < $1
#!/bin/bash
# Usa $IFS para dividir la línea que se está leyendo
# por defecto, la separación es "espacio"
echo "Lista de todos los usuarios:"
OIFS=$IFS # Salva el valor de IFS
IFS=: # /etc/passwd usa ":"para separar los campos
cat /etc/passwd |
while read name passwd uid gid fullname ignore
do
echo "$name ($fullname)"
done
IFS=$OIFS # Recupera el $IFS original
Ejemplo: lee las 2 primeras líneas de un fichero
if trueEjemplo: lee líneas de teclado y guardalas en un fichero temporal convirtiendo minúsculas en mayúsculas
then
read x
read y
fi < fichero1
#/bin/bash
read buf
while [ "$buf" ]
do
echo $buf
read buf
done | tr 'a-z' 'A-Z' > tmp.$$
$ ls /bin/lsPodemos chequear la salida de dos comandos mediante los operadores && (AND) y || (OR)
/bin/ls
$ echo $?
0
$ ls /bin/ll
ls: /bin/ll: Non hai tal ficheiro ou directorio
$ echo $?
1
comando1 && comando2
comando2 sólo se ejecuta si comando1 acaba bien
comando1 || comando2
comando2 sólo se ejecuta si comando1 falla
$ ls /bin/ls && ls /bin/llEjemplo con ||:
/bin/ls
ls: /bin/ll: Non hai tal ficheiro ou directorio
$ echo $?
1
$ ls /bin/ll && ls /bin/ls
ls: /bin/ll: Non hai tal ficheiro ou directorio
$ echo $?
1
$ ls /bin/ls || ls /bin/ll
/bin/ls
$ echo $?
0
$ ls /bin/ll || ls /bin/ls
ls: /bin/ll: Non hai tal ficheiro ou directorio
/bin/ls
$ echo $?
0
if comando1
then
ejecuta otros comandos
elif comando2
then
ejecuta otros comandos
else
ejecuta otros comandos
fi
$ cat if.sh
#!/bin/bash
if (ls /bin/ls && ls /bin/ll) >/dev/null 2>&1
then
echo "Encontrados ls y ll"
else
echo "Falta uno de los ficheros"
fi
$ bash if.sh
Falta uno de los ficheros
test expresióno bien
[ expresión ]3Si la expresión es correcta test devuelve un código de salida 0, si es falsa, devuelve 1:
if [ "$1" = "hola" ]
then
echo "Hola a ti también"
else
echo "No te digo hola"
fi
if [ $2 ]
then
echo "El segundo parámetro es $2"
else
echo "No hay segundo parámetro"
fi
Expresión | Verdadero sí |
string | el string es no nulo ("") |
-z string | la longitud del string es 0 |
-n string | la longitud del string no es 0 |
string1 = string2 | los strings son iguales |
string1 != string2 | los strings son distintos |
Expresión | Verdadero sí |
int1 -eq int2 | los enteros son iguales |
int1 -ne int2 | los enteros son distintos |
int1 -gt int2 | int1 mayor que int2 |
int1 -ge int2 | int1 mayor o igual que int2 |
int1 -lt int2 | int1 menor que int2 |
int1 -le int2 | int1 menor o igual que int2 |
Expresión | Verdadero sí |
-e file | file existe |
-r file | file existe y es legible |
-w file | file existe y se puede escribir |
-x file | file existe y es ejecutable |
-f file | file existe y es de tipo regular |
-d file | file existe y es un directorio |
-c file | file existe y es un dispositivo de caracteres |
-b file | file existe y es un dispositivo de bloques |
-p file | file existe y es un pipe |
-S file | file existe y es un socket |
-L file | file existe y es un enlace simbólico |
-u file | file existe y es setuid |
-g file | file existe y es setgid |
-k file | file existe y tiene activo el sticky bit |
-s file | file existe y tiene tamaño mayor que 0 |
Expresión | Propósito |
! | invierte el resultado de una expresión |
-a | operador AND |
-o | operador OR |
( expr ) | agrupación de expresiones; los paréntesis tienen un significado especial para el shell, por lo que hay que escaparlos |
$ test -f /bin/ls -a -f /bin/ll ; echo $?
1
$ test -c /dev/null ; echo $?
0
$ [ -s /dev/null ] ; echo $?
1
$ [ ! -w /etc/passwd ] && echo "No puedo escribir"
No puedo escribir
$ [ $$ -gt 0 -a \( $$ -lt 5000 -o -w file \) ]
$ [[ -f /bin/ls && -f /bin/ll ]] ; echo $?
1
$ [[ $$ -gt 0 && ($$ -lt 5000 || -w file) ]]
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
#!/bin/bash
echo -n "Respuesta:" read RESPUESTA
case $RESPUESTA in
S* | s*)
RESPUESTA="SI";;
N* | n*)
RESPUESTA="NO ";;
*)
RESPUESTA="PUEDE";;
esac
echo $RESPUESTA
for var in lista
do
comandos
done
LISTA="10 9 8 7 6 5 4 3 2 1"Ejemplo: recorrer los ficheros *.bak de un directorio
for var in $LISTA
do
echo $var
done
dir="/var/tmp"Sintaxis alternativa, similar a la de C
for file in $dir/*.bak
do
rm -f $file
done
LIMIT=10
for ((a=1, b=LIMIT; a <= LIMIT; a++, b--))
do
echo "$a-$b"
done
while comando
do
comandos
done
while [ $1 ]
do
echo $1
shift
done
until comando
do
comandos
done
until [ "$1" = ""]
do
echo $1
shift
done
# Imprime el contenido de los ficheros hasta queEjemplo con continue:
# 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
# Muestra un fichero pero no las líneas de más
# de 80 caracteres
while read buf
do
cuenta=`echo $buf | wc -c`
if [ $cuenta -gt 80 ]
then
continue
fi
echo $buf
done < $1
funcion() {y para llamarla:
comandos
}
funcion p1 p2 p3Siempre tenemos que definir la función antes de llamarla:
#!/bin/bash
# Definición de funciones
funcion1() {
comandos
}
funcion2() {
comandos
}
# Programa principal
funcion1 p1 p2 p3
$ cat funcion1.sh
#!/bin/bash
funcion1()
{
echo "Parámetros pasados a la función: $*"
echo "Parámetro 1: $1"
echo "Parámetro 2: $2"
}
# Programa principal
funcion1 "hola" "que tal estás" adios
$
$ bash funcion1.sh
Parámetros pasados a la función: hola que tal estás adios
Parámetro 1: hola
Parámetro 2: que tal estás
#!/bin/bash
funcion2() {
if [ -f /bin/ls -a -f /bin/ln ]; then
return 0
else
return 1
fi
}
# Programa principal
if funcion2; then
echo "Los dos ficheros existen"
else
echo "Falta uno de los ficheros - adiós"
exit 1
fi
sort $largefile > $newfile &Si lanzamos varios procesos en background podemos usar $!
ejecuta comandos
wait
usa $newfile
sort $largefile1 > $newfile1 &
SortPID1=$!
sort $largefile2 > $newfile2 &
SortPID2=$!
ejecuta comandos
wait $SortPID1
usa $newfile1
wait $SortPID2
usa $newfile2
$ cat trap.shLas señales más comunes para usar con trap son:
#!/bin/bash
cachado() {
echo "Me has matado!!!"
kill -15 $$
}
trap "cachado" 2 3
while true; do
true
done
$ bash trap.sh
(Ctrl-C)
Me has matado!!!
Terminado
Señal | Significado |
0 | salida del shell (por cualquier razón, incluido fin de fichero) |
1 | colgar |
2 | interrupción (Ctrl-C) |
3 | quit |
9 | kill (no puede ser parada ni ignorada) |
15 | terminate; señal por defecto generada por kill |
a=letraLas versiones de bash a partir de la 2 permiten una forma más simple para las referencias indirectas:
letra=z
# Referencia directa
echo "a = $a" # a = letra
# Referencia indirecta
eval a=\$$a
echo "Ahora a = $a" # Ahora a = z
a=letraOtro ejemplo con eval
letra=z
# Referencia directa
echo "a = $a" # a = letra
# Referencia indirecta
echo "Ahora a = ${!a}" # Ahora a = z
$ cat dni.sh
#!/bin/bash
dniPepe=23456789
dniPaco=98765431
echo -n "Nombre: "; read nombre
eval echo "DNI = \$dni${nombre}"
$ bash dni.sh
Nombre: Pepe
DNI = 23456789
$ cat cuentalineas1.sh
#!/bin/bash
count=0
while read line
do
count=$(expr $count + 1)
done < $1
echo "El fichero $1 tiene $count líneas"
$ time bash cuentalineas1.sh Quijote.txt
El fichero Quijote.txt tiene 36855 líneas
real 0m59.757s
user 0m17.868s
sys 0m41.462s
$ cat cuentalineas2.sh
#!/bin/bash
count=0
while read line
do
count=$(($count+1))
done < $1
echo "El fichero $1 tiene $count líneas"
$ time bash cuentalineas2.sh Quijote.txt
El fichero Quijote.txt tiene 36855 líneas
real 0m1.014s
user 0m0.887s
sys 0m0.108s
$ cat cuentalineas3.sh
#!/bin/bash
count=$(wc -l $1 | cut -d " " -f 1)
echo "El fichero $1 tiene $count líneas"
$
$ time bash cuentalineas3.sh Quijote.txt
El fichero Quijote.txt tiene 36855 líneas
real 0m0.096s
user 0m0.005s
sys 0m0.009s
$ bash -x cuentalineas3.sh Quijote.txt
++ wc -l Quijote.txt
++ cut -d ' ' -f 1
+ count=36855
+ echo 'El fichero Quijote.txt tiene 36855 líneas'
El fichero Quijote.txt tiene 36855 líneas
$ cat cuentalineas3.sh
#!/bin/bash
set -x
count=$(wc -l $1 | cut -d " "-f 1)
set +x
echo "El fichero $1 tiene $count líneas"
$
$ bash cuentalineas3.sh Quijote.txt
++ wc -l Quijote.txt
++ cut -d ' '-f 1
+ count=36855
+ set +x
El fichero Quijote.txt tiene 36855 líneas
Administración de Sistemas e Redes <ASR.USC[at]gmail.com>
Tomás Fernández Pena <tf.pena[at]usc.es>
Última actualización: 30-09-15 17:44 por tomas
Curso de Administración de Sistemas y Redes por Tomás Fernández Pena se distribuye bajo la licencia Creative Commons Recoñecemento-Compartir baixo a mesma licenza. 3.0 España.
Trabajo original en persoal.citius.usc.es/tf.pena/ASR.