Programacion Shell
Programacion Shell
Programacion Shell
htm
Universidad de Sevilla
©2018
ÍNDICE
1O
1.1 Introducción
1.2 Objetivo
2E - .I
3S S -
3.1 Funcionamiento general del shell
3.3.1 Variables
3.4.1 Expansión de ~
1 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
3.5.2 Tuberías
3.5.4 Listas
3.5.7 Funciones
4D -
5P
2 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
6A :D
6.1 Asociación para el Proceso Shell actual
1 Objetivos y alcance
1.1 Introducción
El intérprete de comandos o shell es un programa que permite a los usuarios interactuar con
el sistema, procesando las órdenes que se le indican. Los comandos invocables desde el shell
pueden clasificarse en internos (corresponden en realidad a órdenes interpretadas por el
propio shell) y externos (corresponden a ficheros ejecutables externos al shell). Además de
comandos, los shells ofrecen otros elementos para mejorar su funcionalidad, tales como
variables, funciones o estructuras de control. El conjunto de comandos internos y elementos
disponibles, así como su sintaxis, dependerá del shell concreto empleado.
En los S.O.’s Unix existen múltiples implementaciones de shell (en Windows, el equivalente
serían los programas "command.com" o "cmd.exe"). Atendiendo al shell del que proceden y a
su similitud sintáctica (incluyendo sus comandos internos), los shells de Unix pueden
clasificarse en dos grandes familias (existen algunos shell adicionales, de uso residual y
dentro de los shells de una misma familia también existen diferencias, pero gran parte de su
sintaxis es común):
1. sh (Bourne Shell): este shell fue usado desde las primeras versiones de Unix (Unix
Versión 7). Recibe ese nombre por su desarrollador, Stephen Bourne, de los Laboratorios
Bell de AT&T. A raíz de él han surgido múltiples shells, tales como zsh (Z shell), ash
(almquist shell), bash (Bourne again shell), dash (Debian almquist shell) o ksh
(Korn shell). Por su mayor uso pueden destacarse:
bash : fue desarrollado para ser un superconjunto de la funcionalidad del Bourne
Shell (en la que incluye funcionalidades de ksh y csh), siendo el intérprete de
comandos asignado por defecto a los usuarios en las distribuciones de Linux, por lo
que es el shell empleado en la mayoría de las consolas de comandos de Linux. Se
caracteriza por una gran funcionalidad adicional a la del Bourne Shell. Como
ficheros personales de los usuarios emplea $HOME/.bashrc y .bash_profile .
dash (Debian almquist shell), derivado directo de ash, se caracteriza por ser
mucho más ligero (depende de menos bibliotecas) y rápido que otros shells, tales
como bash, aunque con menos características funcionales. El fichero personal del
usuario es $HOME/.profile .
3 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
ksh (Korn shell): destaca por sus funciones avanzadas para manejar archivos,
pudiendo competir con lenguajes de programación especializados tales como awk o
perl.
Bourne Shell ha llegado a convertirse en un estándar de facto de tal modo que todos los
sistemas Unix tienen, al menos, una implementación del Bourne Shell (o un shell
compatible con él), ubicada en /bin/sh . En el caso concreto de los S.O.’s UNIX Linux,
no existe ninguna implementación del Bourne Shell, manteniéndose la entrada
/bin/sh (así como su manual man sh ) como un enlace simbólico a una
implementación de shell compatible. En concreto:
4 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
1.2 Objetivo
El objetivo es introducir el uso del lenguaje de programación de shell-scripts.
Consecuentemente, nos centraremos en la sintaxis de shell propuesta por el estándar POSIX
IEEE 1003.2 lo que, conforme a lo antes indicado, se traduce en que todo lo visto aquí podrá
ser utilizado en dash, bash y cualquier otro shell que satisfaga dicho estándar. Sobre la base
de este documento podrá profundizarse analizando las funcionalidades adicionales añadidas
por cada shell, siendo de especial interés, dado su uso, las aportadas por bash.
5 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Para que no tenga que escribir los scripts que se muestran en esta página a mano,
puede descargarse dichos scripts así como la solución a los ejercicios propuestos
en el fichero comprimido shellscripts.tar.gz . Descomprímalo con el comando:
script.sh
cd ./script.sh
Además de comandos, los shell-scripts pueden contener otros elementos, aportados por el
shell para mejorar la funcionalidad de los scripts. De forma resumida, la estructura básica de
un shell-script es la siguiente:
6 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_ejemplo.sh
Como contenido del script pueden utilizarse múltiples elementos (comandos, variables,
funciones, estructuras de control, comentarios,...) que se analizarán en el siguiente apartado.
El "shebang" permite especificar el intérprete de comandos con el que deseamos que sea
interpretado el resto del script cuando se usa invocación implícita (ver más adelante). La
sintaxis de esta línea es la secuencia #! seguida del ejecutable del shell deseado, sobre lo
que deben realizarse la siguientes advertencias:
Es imprescindible que sea la primera línea del script, ya que, en caso contrario, sería
interpretado como un comentario (comienza con el carácter # ).
Puede haber espacios entre #! y el ejecutable del "shell".
El shebang no es obligatorio (cuando se usa invocación implícita, si no se indica se
intentará usar el mismo tipo de shell desde el que se ha invocado el script).
Sintaxis estricta
La utilización del shebang está condicionada por la forma en que sea invocado el shell-script,
existiendo 3 opciones:
7 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
En los casos en los que se crean subshells, salvo que se fuerce lo contrario (con su -c por
ejemplo), el subshell pertenecerá al mismo usuario al que pertenecía el shell padre que lo ha
creado. El usuario al que pertenece el proceso shell que interpreta un script condiciona las
operaciones que se podrán hacer desde dentro del script (por ejemplo, si el shell pertenece al
usuario dit , el script no podrá modificar el fichero /etc/passwd , mientras que si el shell
pertenece al superusuario root , sí podrá hacerlo). Tenga en cuenta este aspecto para
determinar qué operaciones puede realizar dentro de un script, y con qué usuario debe
invocarlo.
/bin/sh script_ejemplo.sh
TAREAS
/bin/dash script_ejemplo.sh
/bin/bash script_ejemplo.sh
. script_ejemplo.sh
./script_ejemplo.sh
Conforme se ha indicado en la introducción, si bien tanto bash como dash siguen el estándar
POSIX, especialmente bash añade múltiples extensiones particulares, no soportadas por otros
shells como dash. Consecuentemente, cada vez que diseñemos un script deberemos tener en
cuenta el shell o shells que lo soportan, asegurando que sea invocado por uno de ellos. Para
que se haga una idea de la importancia de este aspecto, considere los dos scripts siguientes,
basados en el uso de la estructura for (que se usará más adelante):
8 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_estandar.sh
script_bash.sh
#!/bin/bash
for ((VAR=0 ; VAR<4 ; VAR++ ))
do
echo $VAR
done
Ambos scripts realizan la misma funcionalidad, pero script_estandar.sh está escrito bajo la
sintaxis POSIX, mientras que script_bash.sh utiliza una sintaxis no estándar soportada por
bash.
/bin/sh script_estandar.sh
/bin/dash script_estandar.sh
TAREAS
/bin/bash script_estandar.sh
/bin/dash script_bash.sh
/bin/bash script_bash.sh
3 Sintaxis de Shell-scripts
En este apartado se describe el lenguaje de comandos shell definido en el estándar POSIX.
9 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Veremos el funcionamiento general del shell, así como su sintaxis. Puede encontrar la
descripción detallada del estándar POSIX en la siguiente dirección:
http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html
Aquí se resumen las características más utilizadas. Se recomienda acudir al estándar para
obtener una descripción más detallada y exhaustiva.
La entrada estándar (teclado por defecto). En este caso el shell se dice que es un shell
interactivo.
Un fichero shell-script.
Los argumentos, con la opción -c al ejecutar el shell. Ejemplo: bash –c "ls –l"
Con las líneas leídas, el shell realiza los siguientes pasos (en este orden):
Advertencia
Cuando se escriben comandos desde el teclado y se intenta introducir un elemento que está
formado por más de una línea, una vez que teclee la primera línea y pulse Intro , el shell
10 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
mostrará el indicador secundario de petición de orden > (en lugar del prompt), solicitándole
que continúe escribiendo el elemento. Cuando el intérprete dé por concluida la introducción
del elemento, la interpretará, volviendo a mostrar el prompt de la línea de comandos. Si
utiliza el cursor ↑ para intentar ver el comando introducido, en general verá cómo el shell
ha rescrito la entrada para aplicarle la sintaxis con la que todo el elemento es escrito en una
sola línea. Si desea cancelar la introducción de una línea (o líneas) sin necesidad de borrar lo
que lleva escrito, puede pulsar Ctrl-C.
TAREAS
Cuando queremos utilizar un carácter especial del shell o una palabra reservada del lenguaje
sin que sea interpretada como tal o prevenir una expansión o sustitución indeseada (las
expansiones y sustituciones se verán en un apartado posterior) es necesario indicárselo al
shell mediante las comillas (simples o dobles) o el carácter de escape. Por ejemplo, para
escribir el nombre de un fichero que contenga espacios, para pasar el símbolo < como
argumento a un programa.
El entrecomillado de una cadena vacía ( '' o " ) genera una palabra vacía (palabra que no
tiene ningún carácter).
cd
echo $PWD
echo \$PWD
echo '$PWD'
11 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
echo "$PWD"
echo hola \> a y b
echo hola > a y b #se crea el fichero a
ls
cat a
echo hola >"a y b" #se crea el fichero 'a y b'
ls
cat a\ y\ b
A continuación se detallan cada uno de estos tipos. Vea el apartado 2.5 del estándar para
obtener más información.
3.3.1 Variables
El shell permite realizar las siguientes operaciones básicas con las variables:
VAR=""
Sólo Definición
VAR=
Definición y/o
VAR=valor
Inicialización/Modificación
$VAR
Expansión (Acceso a Valor)
${VAR}
12 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
1. Definición y uso:
Las variables sólo existen en el proceso shell en que son definidas (locales al
proceso).
Las variables sólo son accesibles desde el momento de su definición hacia abajo del
script, esto es, siempre deben definirse primero e invocarse después (no puede
usarse una variable que es definida más adelante). Pueden utilizarse también
dentro de funciones (ver más adelante) aunque se hayan declarado fuera de ellas.
En el estándar POSIX todas las variables son globales, aunque existen variantes
(como bash ) que permiten la creación de variables locales a las funciones.
VAR=
VAR=""
Con el comando set (sin argumentos) puede ver todas las variables (y funciones)
definidas en el shell actual.
13 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_variables.sh
Existe un conjunto de variables que afectan al funcionamiento del shell. Muchas ya han sido
analizadas en temas anteriores, por ejemplo: HOME , PATH , LANG ,... Puede volver a ver
una descripción de ellas en el apartado 2.5.3 del estándar.
Aquí vamos a destacar la variable IFS (Input Field Separators). El valor de esta variable es
una lista de caracteres que se emplearán en el proceso de división de campos realizado tras
el proceso de expansión (que se verá más adelante, en el apartado 3.4) y por el comando
read (ver el apartado 3.8.1 de comandos internos). El valor por defecto es
<espacio><tab><nueva-línea> . Podrá ver un ejemplo de uso de esta variable cuando realice
los ejercicios propuestos (ver solución a script_user.sh).
Son los parámetros de la línea de comandos con la que se ha invocado al script (equivalen a
la variable argv de C). Están denotados por un número y para obtener su valor se emplea
$X o ${X} para los parámetros del 1 al 9 y ${X} para parámetros mayores (números de
más de un dígito). Se pueden modificar con los comando set (los crea) y shift (los
desplaza de posición).
Son parámetros identificados por un carácter especial creados por el Shell y cuyo valor no
puede ser modificado directamente. En esta tabla se muestran los parámetros especiales
definidos en el estándar:
14 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
15 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_var-shell.sh
#!/bin/sh
echo \$@=$@
echo \$*=$*
echo \$0=$0
echo \$1=$1
echo \$2=$2
echo Cambio parametros posicionales
set uno dos tres
echo \$1=$1
echo \$2=$2
TAREAS
echo Desplazo
shift
echo \$1=$1
echo \$2=$2
echo \$-=$-
echo \$#=$#
echo \$?=$?
firefox &
ps w
echo \$$=$$
echo \$!=$!
Cuando un proceso (proceso padre, como por ejemplo el shell) ejecuta otro proceso (proceso
hijo, otro programa o script), el proceso padre, además de los parámetros habituales ( argc
y argv en C), le pasa un conjunto de variables de entorno al proceso hijo (cada lenguaje de
programación tiene su método propio para obtenerlas y modificarlas). Las variables de
entorno pasadas pueden ser utilizadas por el proceso hijo para modificar su comportamiento.
Por ejemplo, un programa en C puede usar la función getenv declarada en biblioteca
estándar stdlib.h para obtener dichas variables (puede obtener más información
ejecutando man getenv ).
El comando interno del shell export permite que una variable (previamente definida o no)
sea configurada para que su valor sea copiado a los procesos hijos que sean creados desde el
shell actual (por ejemplo otros shell). Presenta la sintaxis:
export VAR
export VAR=valor
16 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
En este último caso, sí es posible añadir un espacio antes o después del signo = .
Debe advertirse que "exportación" significa "paso de parámetros por valor", esto es, en el
proceso hijo se creará una variable de igual nombre que en el shell padre, y con igual valor,
pero serán variables independientes (esto es, la modificación de valor de la variable en el
proceso hijo no afectará al valor de la variable en el shell padre). El proceso hijo no puede
crear ni modificar variables del proceso padre.
script_padre.sh
#!/bin/bash
export VAR=a
echo $VAR
ps w
./script_hijo.sh
echo $VAR
TAREAS
script_hijo.sh
#!/bin/sh
echo $VAR
VAR=b
echo $VAR
ps w
./script_padre.sh
Analice el resultado.
17 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script1.sh
#!/bin/bash
VAR=a
echo $VAR
ps w
. script2.sh
echo $VAR
script2.sh
#!/bin/sh
echo $VAR
VAR=b
echo $VAR
ps w
./script1.sh
En los S.O.'s Linux suele ser habitual encontrar scripts que se dedican exclusivamente a
contener la inicialización de un conjunto de variables, o la definición de un conjunto de
funciones. Otros scripts del sistema hacen uso del mecanismo de invocación implícito basado
en . , para cargar o importar las variables o funciones definidas en dichos scripts.
cont_func.sh
#!/bin/sh
fun1(){...}
fun2(){...}
#...
cont_var.sh
#!/bin/sh
VARa=1
VARb=2
#...
18 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_sistema.sh
#!/bin/sh
. /dir/cont_var.sh
. /dir2/cont_fun.sh
fun1 $VARb
#...
Por ejemplo, visualice el contenido del script del sistema encargado del arranque de
los servicios /etc/init.d/rc . Observe cómo contiene las líneas:
. /etc/default/rcS
. /lib/lsb/init-functions
TAREAS
Aparte de estas expansiones está el concepto de alias (ver apartado 2.3.1 del estándar) que
se utiliza para crear sinónimos de comandos y sólo se realiza en el elemento ejecutable de la
19 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
línea antes de cualquier otra expansión o sustitución. Su utilización es muy limitada y puede
conseguirse un comportamiento similar usando funciones que permiten además parámetros
(las funciones se verán más adelante). Puede ver los alias definidos usando el comando
alias . Puede ver ejemplos de definición de alias en el fichero ~/.bashrc .
Puede utilizar las expansiones en cualquier ubicación donde se pueda usar una cadena de
texto (incluido el nombre de comandos), exceptuando las palabras reservadas del lenguaje (
if , else , …).
3.4.1 Expansión de ~
Variables Valor
20 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
./script_var-shell.sh ~ ~root
El formato general para incluir una expansión de variables o parámetros, como se ha visto en
apartados anteriores es:
${PAR}
Las llaves pueden omitirse, salvo cuando se trate de un parámetro posicional con más de un
dígito o cuando se quiera separar el nombre de la variable de otros caracteres. Por ejemplo:
Aparte de este formato general, se pueden utilizar otros formatos que permiten establecer
valores por defecto, comprobar si la variable está definida, eliminar sufijos y prefijos, contar
el número de caracteres, etc. Puede ver la lista de formatos junto con ejemplos en el
apartado 2.6.2 del estándar. Por ejemplo, los siguientes:
21 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_expansion1.sh
#!/bin/sh
VAR=1
echo $VAR
unset VAR
echo ${VAR:-2}
echo $VAR
FICH=fichero.c
echo ${FICH%.c}.o
22 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_expansion2.sh
#!/bin/sh
VAR=1
echo $VAR
unset VAR
echo ${VAR:=2}
echo $VAR
FICH=/usr/bin/prueba
echo ${FICH##*/}
TAREAS
Permite que la salida estándar de un programa se utilice como parte de la línea que se va a
interpretar.
$(comando)
`comando`
En el segundo caso se está utilizando la tilde francesa o acento grave, que no debe
confundirse con las comillas simples. Para escribirla, hay que pulsar la tecla correspondiente a
` y pulsar espacio.
Por ejemplo, para almacenar en una variable el nombre de todos los ficheros con extensión
.sh del directorio actual, podría escribir:
VAR=`ls *.sh`
O, por ejemplo, para matar el proceso con nombre firefox-bin , podría usar:
$((expresión))
23 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Permite evaluar las cadenas indicadas en la expresión como enteros, admitiendo gran parte
de los operadores usados en el lenguaje C, pudiendo usar paréntesis como parte de la
expresión y el signo - para números negativos (a las cadenas que contengan letras se les
asigna el valor 0 ). Tras la evaluación aritmética, el resultado vuelve a ser convertido a una
cadena. La conversión de un número a un carácter puede realizarse con $'\xxx' (en bash )
o con '\xxx' (en dash ), ambos con comillas simples, pero ello no está recogido en el
estándar POSIX.
script_expansion3.sh
#!/bin/sh
VAR=1
VAR=$VAR+1
echo $VAR
TAREAS
RES1=$(($VAR))+1
echo $RES1
VAR=1
RES2=$((VAR+1)) #VAR no necesita $
echo $RES2
VARb=b
echo $(($VARb+1)) #VARb necesita $
./script_expansion3.sh
Analice el resultado.
eliminando las líneas con la palabra "firefox", para evitar que moleste en las
siguientes pruebas. Ejecute los siguientes comandos observando el valor de la
variable especial @ :
24 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
./script_var-shell.sh script_for?.sh
./script_var-shell.sh script_for*.sh
./script_var-shell.sh script_expansion*.sh
./script_var-shell.sh script_expansion[12].sh
./script_var-shell.sh script_e*.sh
a. Comandos simples
b. Tuberías
c. Listas AND-OR
d. Listas
e. Listas compuestas
f. Comandos compuestos (o estructuras de control)
g. Definiciones de función
Cada uno de estos tipos se forma mediante la composición de elementos de los tipos inferior.
Pero también se permite anidar distintos tipos de comandos (no todas las combinaciones son
posibles como se verá más adelante), por lo que podríamos encontrarnos: tuberías de
comandos compuestos, comandos compuestos formados por otros comandos compuestos,
etc.
En general, el valor devuelto por un comando compuesto (tipo b y superiores) será el valor
devuelto por el último comando simple ejecutado.
A continuación describiremos cada uno de los tipos. Puede ver más detalles en el apartado
2.9 del estándar.
Un comando simple está formado por (todos los elementos son opcionales) una secuencia de
asignación de variables y redirecciones (en cualquier orden) seguida de palabras (elemento
ejecutable y sus argumentos) y redirecciones. A continuación se muestra la estructura
genérica de un comando simple (los corchetes [ ] indican qué elementos son opcionales,
que es la notación usada en el resto de este documento):
25 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
VAR=x
El anterior comando asigna el valor x a la variable VAR y afecta a todo el proceso shell
actual.
VAR=x programa
VAR=y OTRA=z
echo $VAR
Se asigna el valor y a la variable VAR y el valor z a la variable OTRA , que afectan a todo
el shell. A continuación, asigna el valor x a la variable VAR y afecta sólo al programa, al
cual se le pasa como primer argumento y . A continuación se imprime y por pantalla.
Ambas líneas, asignan el valor x a la variable VAR que afecta solo al programa. Se ejecuta
el programa y la salida estándar se redirige al archivo fichero . La redirección se realiza
independientemente de que aparezca antes o después del programa. Si hubiera varias
redirecciones se realizan en el orden de aparición en la línea, de izquierda a derecha.
3.5.2 Tuberías
Una tubería es una secuencia de uno o más comandos (simples o compuestos, pero no
ningún tipo de lista) separados por el operador | . La salida estándar de un comando se
conecta a la entrada estándar del siguiente comando (cada comando se ejecuta en otro
subshell simultáneamente). Esta conexión se hace previamente a cualquier redirección. El
formato es:
[ ! ] comando1 [ | comando2 … ]
Opcionalmente, se puede añadir delante el carácter ! que hace la negación lógica del valor
devuelto por el último comando, de tal manera que el valor devuelto por la tubería sería 1 si
el último comando devuelve 0, o 0 en caso contrario.
Una lista AND es una secuencia de tuberías (tenga en cuenta que una tubería puede ser sólo
26 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Se van ejecutando las tuberías de izquierda a derecha hasta que una de ellas devuelva un
valor distinto de cero. No se realiza ninguna expansión en una tubería hasta que el shell no
determine que tiene que ejecutar dicha tubería (dependerá del resultado de la tubería
anterior).
Una lista OR es una secuencia de tuberías separadas por el operador || . El formato es:
tuberia1 [ || tuberia2 … ]
Se van ejecutando las tuberías de izquierda a derecha hasta que una de ellas devuelva un
valor cero. No se realiza ninguna expansión en una tubería hasta que el shell no determine
que tiene que ejecutar dicha tubería.
Una lista AND-OR es el resultado de combinar listas AND y/o OR en una misma línea. Los
operadores && y || se evalúan con la misma prioridad de izquierda a derecha. Ejemplo:
3.5.4 Listas
Las listas son secuencias de una o más listas AND-OR separadas por los operadores ; o & .
Los operadores ; y & no pueden aparecer seguidos (por ejemplo, daría error prog1 & ;
prog2 )
Según el operador las listas pueden ser secuenciales, asíncronas o mixtas (combinación de
ambas).
listaAND-OR1 [ ; listaAND-OR2 … ] [ ; ]
Se utiliza como separador el operador & . Se van ejecutando los distintos comandos sin
esperar a que el comando anterior termine (ejecución en segundo plano). El formato es:
En este caso, a menos que se haga una redirección explícita de la entrada estándar, si un
programa en segundo plano lee de la entrada estándar recibirá un error de fin de fichero
(EOF).
27 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
No es más que una secuencia de listas (apartado 3.5.4), separadas por el carácter de nueva
línea (intros), terminada por el operador ; , el operador & , el carácter de nueva línea
(intro) o un comando compuesto. La utilidad de este tipo de listas se verá sobre todo cuando
se expliquen los comandos compuestos.
script_operadores.sh
#!/bin/sh
head -1 /etc/passwd && echo "Sin error1A" || echo "Con error1B"
head -1 /nofile && echo "Sin error2A" || echo "Con error2B"
TAREAS
Desde la línea de comandos, cree listas y tuberías de todos los tipos vistos usando
combinaciones de los comandos ls , echo , cat y ps .
Los comandos compuestos son lo que en otros lenguajes de programación se conocen como
estructuras de control. Cada uno de estos comandos compuestos (o estructuras de control)
están delimitados por una palabra reservada u operador de control al principio y otro al final
(terminador). Si se hace una redirección a continuación del terminador, en la misma línea,
esa redirección se aplicará a todos los comandos que se encuentre en ese comando
compuesto, a menos que se haga otra redirección explícita en un comando en concreto.
La agrupación de comandos permite mejorar la legibilidad del código, aplicar una redirección
a un conjunto de comandos y crear un subshell entre otras cosas.
28 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
( lista-compuesta )
{ lista-compuesta }
Se ejecuta la lista compuesta en el shell actual. Recuerde que las listas compuestas
están terminadas por los operadores ; , & o nueva línea (el último comando debe
estar separado de la llave de cierre por esos operadores).
En ambos casos, se permite añadir una redirección al final (detrás del ) o } ) que afectará
a todos los comandos del grupo.
if lista-compuestaA1 then
lista-compuestaB1
elif lista-compuestaA2 then
lista-compuestaB2
...
else
lista-compuestaN
fi
Las entradas elif tienen el significado de un else seguido de un nuevo if . Puede haber
tantas entradas elif como se desee. Tanto las entradas elif como la entrada else son
opcionales.
29 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
if condicion if condicion
then then
comando1; comando1
comando2; comando2
fi fi
Recuerde que si usa las llaves, debe separarlas del resto de elementos. Por ejemplo:
Respecto a la condición ; que puede usarse, basta cualquier lista compuesta que devuelva
un valor (por ejemplo, pueden usarse los comandos internos true o false ). El valor de
una lista compuesta es el valor del último comando simple ejecutado en la lista compuesta.
test expresion
En la segunda forma los corchetes no son operadores ni indican que la expresión sea
opcional, sino que realmente son el nombre del programa.
Puede ver la descripción del comando test según el estándar en la siguiente URL:
http://pubs.opengroup.org/onlinepubs/009695399/utilities/test.html
30 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
n1 -eq n2 n1 = n2
n1 -ne n2 n1 ≠ n1
n1 -gt n2 n1 > n2
Enteros (n1 y
n2 se
convierten a
enteros)
n1 ≥ n2
n1 –ge n2
n1 -lt n2 n1 < n2
n1 -le n2 n1 ≤ n2
Cadenas
31 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
-z "$VAR"
"$VAR"
Ficheros
32 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Cualquiera de las condiciones anteriores puede ser precedida por el operador negación ! , en
cuyo caso la condición será cierta si no se satisface la comparación indicada. Por ejemplo, !
-d $DIR se cumplirá si $DIR NO es un directorio.
33 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Recuerde las restricciones de sintaxis del shell en lo que respecta a los espacios,
especialmente importantes en la escritura de las condiciones. Por ejemplo, la siguiente
entrada dará error de sintaxis (el espacio tras ; sí puede omitirse):
Y la siguiente dará error porque buscaría el comando [comando] (incluyendo los corchetes
como parte del nombre del comando), que en general no encontrará (mostrando un mensaje
de orden no encontrada).
if [comando]; then
script_if.sh
#!/bin/sh
FILE=/tmp/archivo
TAREAS
VAR1=1; VAR2=1
if [ $(($VAR1)) -ne $(($VAR2)) ]; then
echo Distintos
elif ls /; then
:
fi
rm –f /tmp/archivo
./script_if.sh
touch /tmp/archivo
chmod –w /tmp/archivo
34 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
./script_if.sh
case cadena_texto in
patron1) lista-compuesta1;;
patron2) lista-compuesta2;;
...
* ) lista-defecto [;;] #patron coincidente con todo
esac
patronA | patronB)
(patronA | patronB)
(patronC)
El doble punto y coma ;; permite determinar el final de los elementos a interpretar cuando
se cumpla su patrón asociado. Por ese motivo, el ;; del último patrón puede omitirse. Es
posible añadir espacios entre los patrones y los paréntesis abiertos ) que marcan el final del
patrón. Conforme a esto, serían sintaxis válidas alternativas las siguientes:
35 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_case.sh
#!/bin/sh
case $1 in
archivo | file)
echo Archivo ;;
*.c)
TAREAS
echo Fichero C ;;
*)
echo Error
echo Pruebe otro ;;
esac
./script_case.sh archivo
./script_case.sh file
./script_case.sh file.c
./script_case.sh file.c++
36 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
El nombre de la variable VAR debe aparecer obligatoriamente junto con la palabra reservada
for en la misma línea. lista_valores debe estar obligatoriamente en la misma línea que
la palabra reservada in . El punto y coma ; puede sustituirse por un salto de línea, y
viceversa. Así, por ejemplo, serían sintaxis válidas las siguientes:
lista_valores se corresponde con un conjunto de valores (tomándose cada valor como una
cadena de caracteres que puede ser objeto de expansión y como caracteres de separación los
caracteres definidos en la variable IFS ). La estructura for define la variable VAR (si no
ha sido previamente definida). Para cada uno de los valores del resultado de expandir
lista_valores , la estructura inicializa la variable VAR con dicho valor y realiza una
iteración (ejecutando lista-compuesta, en la cual suele ser habitual acceder al valor de la
variable VAR ).
script_for1.sh
#!/bin/sh
for i in 1 2 3; do
echo "Iteracion: $i"
done > ficherosalida
37 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_for2.sh
#!/bin/sh
Suele ser habitual el uso del comando externo seq para generar una lista de valores. Si bien
este comando no está recogido en el estándar POSIX, es habitual su presencia en la mayoría
de los sistemas UNIX. El comando seq presenta la sintaxis:
siendo ambos valores números enteros. La salida del comando es la secuencia de números
enteros entre ambos valores extremos indicados.
seq 1 10
script_for_seq.sh
#!/bin/sh
38 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
La lista-comp-condicion es una lista compuesta que se rige por las mismas directrices
indicadas en la estructura if . La estructura:
Así, por ejemplo, serían válidas y equivalentes las sintaxis siguientes, si la condición del
until es la condición del while negada:
script_while.sh
#!/bin/sh
TAREAS
CONTADOR=0
while [ $CONTADOR – lt 3 ]; do
echo "Contador: $CONTADOR "
CONTADOR=$(($CONTADOR+1))
done
39 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_until.sh
#!/bin/sh
CONTADOR=0
until [ $CONTADOR – ge 3]]; do
echo El contador es $CONTADOR
CONTADOR=$(($CONTADOR+1))
done
En shell script esto se realiza con dos comandos internos: continue y break
continue [n]
b. break : utilizado en estructuras de control repetitivas para detener todas las iteraciones
restantes de la estructura de control actual. Su sintaxis es:
break [n]
3.5.7 Funciones
40 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
El paréntesis siempre debe estar vacío (sólo indica que se está definiendo una función).
Pueden insertarse espacios antes, entre y después del paréntesis. El comando compuesto
puede ser cualquier de los que se han visto (agrupación de comandos, estructuras
condicionales, estructuras repetitivas). Opcionalmente pueden aplicarse redirecciones a la
función (afecta a los comandos que contiene, salvo que contengan una redirección explícita).
A continuación se muestran ejemplos básicos de definición de funciones:
fnombre(){ fnombre(){
comando1 comando1;
comando2 comando2;
} }
En lo que se refiere al nombrado de las funciones, se aplican los mismos criterios antes
expuestos para el nombrado de las variables.
El estándar permite que dentro de una función se invoque a otra. Los argumentos pasados a
la función en su invocación son accesibles desde el cuerpo de la función mediante los
parámetros posicionales $1 , $2 ,..., $9 , ${10} ,... Por tanto, dentro de la función, los
parámetros posicionales no corresponden a los argumentos usados en la invocación del script.
Dentro del cuerpo de la función suele ser habitual el uso del comando return , el cual
provoca la salida inmediata de la función con el valor de retorno (número) indicado:
return [n]
41 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Si no se indica ningún valor de retorno, la función devuelve el valor del último comando
ejecutado. Como siempre, el valor devuelto por la función puede obtenerse con la variable
$? . return también puede utilizarse para terminar un script invocado implícitamente con
. .
Mire el contenido del siguiente script en su sistema, compruebe que tiene el permiso
de ejecución, invóquelo con 2 números enteros como argumentos y analice su
funcionamiento :
script_funcion.sh
#!/bin/sh
TAREAS
suma () {
C=$(($1+$2))
echo "Suma: $C"
return $C
echo "No llega"
}
suma 1 2
suma $1 $2 #suma los 2 primeros argumentos pasados al script
echo "Valor devuelto: " $?
Los comandos internos corresponden a órdenes interpretadas por el propio shell (luego no
existe ningún fichero ejecutable asociado al comando). Se distinguen dos tipos de comandos
internos:
Especiales: un error producido al ejecutar este comando da lugar a que el shell termine.
Por consiguiente, el script termina con un error y un valor de retorno mayor de cero (vea
el apartado 2.8.2 del estándar para saber el valor de retorno).
Regulares: el shell no tiene que terminar cuando se produce un error en estos
comandos.
42 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
43 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
http://pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html
Básicos regulares bg, cd, false, fg, jobs, kill, pwd, read, true, wait
Para Profundizar
alias, command, fc, getopts, newgrp, umask, unalias
regulares
Consulte: http://pubs.opengroup.org/onlinepubs/009695399/utilities
/xcu_chap01.html#tagtcjh_5
Entre dichos comandos (especiales y regulares), por su utilidad en los shell-scripts deben
destacarse los siguientes:
exit [n]
exit provoca la eliminación inmediata del proceso correspondiente al shell que está leyendo
el script. El parámetro opcional es un número entero que corresponde al valor devuelto por el
script. Si no se indica ningún parámetro, el valor devuelto por el script será el del último
comando ejecutado.
1. Abra una consola de comandos. Mediante el comando su abra una sesión con
el superusuario. Al abrir la sesión con root , se ha creado un nuevo proceso en
memoria correspondiente al shell encargado del intérprete de comando en la
sesión del root . Use el comando ps ax para localizar dicho proceso.
2. Ejecute el comando exit , volviendo al usuario normal. Esto habrá provocado
la eliminación del proceso shell encargado de la línea de comandos como en la
TAREAS
script_exit.sh
echo Dentro del script
exit 3
echo Fuera del script
44 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
/bin/bash script_exit.sh
./script_exit.sh
. script_exit.sh
El comando read read lee una línea de la entrada estándar (teclado) y la guarda en
variables. Solo funciona en shell interactivos (leyendo la entrada del teclado), de lo contrario
no hace nada. En su forma más básica, presenta la siguiente sintaxis:
45 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Este comando espera a que el usuario introduzca una línea de texto incluyendo espacios (la
entrada termina cuando el usuario pulsa la tecla "Intro"; la pulsación "Intro" no forma parte
del valor asignado a la cadena). Esta línea se divide en campos (según la variable IFS ). Tras
ello, el comando define las variables dadas como argumentos, inicializándolas con los campos
obtenidos en la división. Si hay más campos que variables, los campos restantes se asignan a
la última variable. Si hay más variables que campos, las variables sobrantes reciben como
valor la cadena vacía "" .
Algunos intérpretes de comandos como bash añaden otras opciones a este comando, como
la posibilidad de imprimir un mensaje usando la opción -p (vea la ayuda de read en
bash con el comando man bash ).
script_read.sh
El comando read también puede ser útil, por ejemplo, para detener la interpretación del
script hasta que el usuario pulse una tecla:
script_read_pause.sh
TAREAS
Resulta habitual el uso de estructuras while , combinadas con case y read , para crear
menús interactivos, permitiendo mantenerse dentro del menú.
TAREAS
46 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_case_menu.sh
#!/bin/sh
clear
SALIR=0
OPCION=0
while [ $SALIR -eq 0 ]; do
echo "Menu:"
echo "1) Opcion 1"
echo "2) Opcion 2"
echo "3) Salir"
echo "Opcion seleccionada: "
read OPCION
case $OPCION in
1)
echo "Opcion 1 seleccionada" ;;
2)
echo "Opcion 2 seleccionada" ;;
3)
SALIR=1 ;;
*)
echo "Opcion erronea";;
esac
done
script_case_menu.sh
eval [argumentos …]
47 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
script_eval.sh
Básicos cat, chmod, chown, cmp, date, cp, dirname, echo, printf, expr
Para
awk, basename, chgrp
Profundizar
echo Uno
echo –e "Uno\nDos"
4 Depuración de shell-scripts
48 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
También es posible depurar sólo parte del script insertando en él los siguientes comandos
(pueden usarse igualmente en la propia línea de comandos):
script_depuracion.sh
#!/bin/sh
TAREAS
echo Hola
if true; then
echo hola2
ls /
fi
49 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
/bin/bash script_depuracion.sh
/bin/bash -x script_depuracion.sh
/bin/bash -v script_depuracion.sh
/bin/dash -x script_depuracion.sh
/bin/dash -v script_depuracion.sh
script_depuracion2.sh
#!/bin/sh
echo Hola
set -xv
if true; then
echo hola2
ls /
fi
set +xv
script_depuracion2.sh
/bin/dash script_depuracion2.sh
/bin/bash script_depuracion2.sh
5 Propuesta de ejercicios
A continuación se le propone la creación de una serie de scripts. Para ello, será necesario
tanto usar los conocimientos expuestos en este documento, como otros relativos a la
administración de Linux:
a. Los ficheros /etc/profile (leído en el arranque del sistema y común para todos los
usuarios), ~/.bashrc , ~/.bash_profile (leídos al abrir una sesión con el usuario
correspondiente, no es necesario que existan ambos), usados para cargar las variables
de entorno, son en realidad shell-scripts. Analice el contenido de dichos scripts y
modifíquelos convenientemente para definir los alias:
alias red='ifconfig -a' : para todos los usuarios del sistema.
alias casa='echo $PWD' : sólo para el usuario normal.
alias sockets='netstat -l' : sólo para el usuario root .
50 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
51 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
El script debe comprobar si los argumentos pasados son correctos, así como la
existencia del usuario indicado. Como código de error podrá devolver 0 (éxito), 1
(sintaxis de invocación errónea), 2 (usuario no existe).
l. script_menu.sh : script que ofrezca al usuario un menú (con una opción para salir)
desde el que el usuario pueda seleccionar cual de los scripts anteriores (apartados "b)" a
"k)") quiere utilizar.
m. script_puerto.sh : script que reciba como argumento un número de puerto TCP
(PUERTO) y comprobará si el valor es un número entero positivo en el rango "[1, 1023]",
de modo que:
Si es así: el script analizará si los puertos TCP "PUERTO" y "PUERTO+1" del equipo
local se encuentran a la escucha. Tras ello, imprimirá un mensaje indicando el
estado obtenido. Para ello, puede analizar la salida del comando netstat .
En otro caso: imprimirá por pantalla un mensaje indicando que el valor indicado no
es un puerto de sistema.
n. script_arp.sh : script que reciba como argumento un número entero, guardándolo en
la variable POS_ARP . El script comprobará si el valor de la variable POS_ARP es un
número entero positivo, de modo que:
Si es así: el script calculará el número de entradas que actualmente tiene la caché
ARP del equipo, guardándolo en la variable NENTRADAS . Si el valor de POS_ARP es
mayor que NENTRADAS , imprimirá por pantalla un mensaje tal como: Ninguna ent
rada ARP en la posición valor_POS_ARP . En caso de que POS_ARP sea menor o
igual que NENTRADAS , imprimirá por pantalla un mensaje con la posición de la
entrada ARP POS_ARP , seguido del contenido de dicha entrada ARP, e.g.: Entrada
valor_POS_ARP de la caché ARP: 172.16.17.254 ether 00:13:f7:0a:18:8b
C eth0 .
En otro caso: Imprimirá por pantalla un mensaje indicando que el valor indicado no
es un número entero: Posición de entrada ARP no válida
52 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
VAR="nombre=valor1&edad=valor2&telefono=valor3"
Escriba un shell-script que analice el valor de dicha variable y para cada uno de los
parámetros extraiga su valor y lo imprima por pantalla. Por ejemplo, que la salida sea:
53 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Recurso Fichero
Directorio /carpeta
Pantalla /dev/ttyXX
Ratón /dev/psaux
Cuando un proceso necesita acceder a un recurso, debe realizar las siguientes operaciones:
1. Abrir el fichero correspondiente a dicho recurso: el proceso indica al sistema la ruta del
fichero, especificando su intención de abrirlo para lectura (obtener información del
recurso), escritura (enviar información al recurso) o lectura/escritura; el sistema
concederá el tipo de acceso solicitado según las características del recurso (teclado,
pantalla, ...) y los permisos que el usuario efectivo del proceso posea sobre el fichero.
Como respuesta, el sistema devolverá al proceso el descriptor (o descriptor de fichero)
con el que el proceso podrá acceder al fichero.
2. Acceder al fichero/recurso usando el descriptor suministrado por el sistema: el proceso
indicará el descriptor al kernel, éste localiza el fichero y accede al recurso asociado.
54 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
kernel proceso
Un descriptor no es más que un número entero "n", con las siguientes características:
Fichero Descriptor
Fichero_A 0
Fichero_B 1
Fichero_C 2
... ...
a. Muchas aplicaciones, especialmente pensadas para ser usadas en modo consola, son
programadas para que, por defecto (sus procesos):
55 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Obtengan datos del (recurso asociado al) descriptor "0": dado que éste es el
descriptor del que convencionalmente las aplicaciones obtienen información, este
descriptor suele denominarse "entrada estándar (a pesar de este nombre, dado
su uso especial, internamente los descriptores “0, 1, 2” son de entrada/salida).
Envíen su información al (recurso asociado al) descriptor "1": dado que éste es el
descriptor al que convencionalmente las aplicaciones envían su información, este
descriptor suele denominarse "salida estándar".
Envíen su información de errores al (recurso asociado al) descriptor "2": dado
que éste es el descriptor al que convencionalmente las aplicaciones envían su
información de errores, este descriptor suele denominarse "salida de error
estándar".
Esta configuración "estándar" es la empleada por los comandos POSIX. Así, por ejemplo,
los comandos "echo cadena" o "cat fichero" están preparados para imprimir (enviar la
información) en el recurso asociado al descriptor 1 (salida estándar), o el comando
cat (sin argumentos) está diseñado para obtener la información del recurso asociado
al descriptor 0 (entrada estándar).
Por omisión, cuando un proceso padre crea un proceso hijo, el proceso hijo sólo dispone
de los descriptores "0, 1, 2", cada uno asociado al mismo recurso que en el proceso
padre (el proceso hijo hereda la asociación descriptor-fichero para esos tres
descriptores, el resto de descriptores no se "heredan"). Todo ello lleva a que en una
consola de comandos, las órdenes "echo cadena" o "cat fichero" suelan imprimir por
pantalla (recurso del descriptor 1 ), o el comando cat (sin argumentos) obtenga la
información del teclado (recurso del descriptor 0 ), al heredar esa asociación descriptor-
fichero del shell (proceso padre).
Para ello, la sintaxis a aplicar varía según el proceso sobre el que queramos establecer la
nueva asociación fichero-descriptor sea el propio proceso shell que estamos utilizando, o
sobre un comando (proceso hijo) invocado desde este shell (en programación C, por ejemplo,
se realizaría con la función "open", entre otras).
56 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
Sintaxis Funcionalidad
Por ejemplo, el siguiente comando permite asociar el archivo /tmp/fichero con el descriptor
"4":
A partir de ello, cada vez que queramos que un comando realice operaciones de
lectura/escritura sobre ese archivo, podremos aplicar los operadores de redirección
(detallados más abajo) con dicho descriptor (en lugar de usar el nombre del archivo). Por
ejemplo, para que el comando ls ; envíe su información a ese archivo:
ls >&4
57 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
donde:
Al aplicar esa redirección sobre el comando, para el descriptor n , el comando (el proceso
hijo que se crea) no heredará (aún en el caso de ser n=0, 1 o 2 ) la asociación descriptor-
fichero del proceso shell padre, sino que asociará a dicho descriptor n el "fichero"
explícitamente indicado.
58 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
59 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
60 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
61 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
comando1 | comando2
62 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
a. Las redirecciones son aplicables a cualquier comando, incluso a subshells (shell abierto
desde otro shell), de modo que todos los comandos abiertos desde dicho subshell
heredarán por defecto su asociación de los descriptores 0, 1, 2 . Por ejemplo, si en un
shell ejecutamos:
con el segundo comando se estará abriendo un nuevo proceso shell (subshell), el cual
tendrá asociado el descriptor 0 con el archivo /tmp/fichero . Si en dicho subshell
abierto ejecutamos ahora:
cat
63 de 64 14/8/2019 10:54
Programación Shell-script en Linux http://trajano.us.es/~fjfj/shell/shellscript.htm
cat << END > fichero : lee información del teclado, hasta que se introduce
una línea con END. Entonces copia toda la información tecleada al archivo
TAREAS
fichero .
ls -l /bin/bash ./script > fichero 2> error : redirige la salida estándar al
archivo fichero y la salida de error al fichero error .
ls -l /bin/bash ./script > fichero 2>&1 : redirige las salidas estándar y de
error al archivo fichero .
ls 2> /dev/null 1>&2 : redirige las salidas estándar y de error al archivo
nulo.
Por último, advertir que la explicación anterior corresponde al estándar POSIX. Algunos
intérpretes de comandos como Bash soportan otros operadores (además de los POSIX). A
continuación se resumen algunos de los ofrecidos por Bash:
64 de 64 14/8/2019 10:54