Ejecución condicional

Otra situación algo más elaborada que la anterior es ejecutar una orden condicionada a la terminación correcta o no de una orden previa.

Esta funcionalidad nos la proporcionan los operadores "&&" y "||".

Operador &&

El primer operador, "&& " separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina correctamente, es decir

orden1 && orden2
              

orden2 sólo se ejecutará si orden1 terminó sin ningún error.

Por ejemplo, queremos ejecutar la orden cat fichero sólo si existe fichero; entonces tendremos que buscar una orden que termine con un error si no existe fichero, por ejemplo ls fichero y condicionar la ejecución de cat fichero a esta:

$ ls fichero && cat fichero
              

Otro ejemplo, para compilar los controladores de dispositivos de linux e instalarlos, lo podemos hacer como:

make module && make modules_install
              

es decir instalará los controladores sólo si ha conseguido compilarlos correctamente.

Operador ||

El segundo operador, "|| " tiene un comportamiento similar al anterior, separa dos órdenes de forma que la que tiene a la derecha sólo se ejecuta cuando la de la izquierda termina incorrectamente, es decir

orden1 || orden2
              

orden2 sólo se ejecutará si orden1 terminó con algún error.

Por ejemplo si no existe fichero queremos crearlo vacía y si existe no hacemos nada. Igual que en el ejemplo anterior, buscamos una orden que termine con un error si no existe fichero y condicionamos la ejecución de la orden touch fichero al error de la orden previa:

$ ls fichero || touch fichero
              

También, al igual que en el ejempo anterior podríamos hacer que si el proceso make modules falla, se borraran todos los ficheros temporales que se crean:

make modules || rm -r *.o
              

Ejecución simultánea

Otra posibilidad de ejecución también posible es lanzar varios procesos simutáneamente en segundo plano; basta escribir uno a continuación de otro en la línea de órdenes separados por "&". Este es el símbolo que se utiliza para indicar que el proceso se tiene que ejecutar en segundo plano, pero también actúa como separador para la ejecución de distintas órdenes.

por ejemplo :

[pfabrega@port pfabrega]$ sleep 10 & sleep 20 & sleep 15 &
[pfabrega@port pfabrega]$ ps axu
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.2  1408  540 ?        S    22:19   0:04 init [3]
...
pfabrega  1263  0.3  0.2  1624  516 pts/4    S    23:24   0:00 sleep 10
pfabrega  1264  0.0  0.2  1624  516 pts/4    S    23:24   0:00 sleep 20
pfabrega  1265  0.0  0.2  1624  516 pts/4    S    23:24   0:00 sleep 15
pfabrega  1266  0.0  0.3  2732  848 pts/4    R    23:24   0:00 ps axu
              

Agrupando con paréntesis

Podemos organizar la ejecución de varias órdenes agrupándolas convenientemente mediante paréntesis para modificar el orden predeterminado de ejecución. En primer lugar actúan los ; después los & y la ejecución es de izquierda a derecha. Para las ejecuciones condicionales se tiene en cuenta el valor de la variable $? que se fija por la última orden que se ejecuta.

Para alterar esta forma de ejecución podemos utilizar los paréntesis. En realidad los paréntesis fuerzan una nueva subshell para ejecutar las órdenes correspondientes.

Esta característica puede ser interesante en diferentes situaciones:

Quemos enviar una secuencia de órdene s a segundo pláno

(mkdir copiaseg; cp -r ./original/* ./copiaseg; rm -r ./original~; rm -r ./original.tmp) &
              

Resultado de la ejecución de una orden

Es habitual necesitar almacenar el resultado de la ejecución de una orden en una variable en lugar de que se dirija a la salida estándar o simplemente ejecutar como orden el resultado de otra orden.

Comillas invertidas `

Las comillas invertidas consideran una orden lo que tengan dentro y lo ejecutan devolviendo el resultado como líneas de texto a la shell. Por ejemplo:

$ A="ls /bin"
$ `echo $A`
arch        consolechars   ed          igawk     mount          rpm        tar
ash         cp             egrep       ipcalc    mt             rvi        tcsh
ash.static  cpio           ex          kill      mv             rview      touch
awk         csh            false       ln        netstat        sed        true
basename    date           fgrep       loadkeys  nice           setserial  umount
bash        dd             gawk        login     nisdomainname  sfxload    uname
bash2       df             gawk-3.0.6  ls        ping           sh         usleep
bsh         dmesg          grep        mail      ps             sleep      vi
cat         dnsdomainname  gtar        mkdir     pwd            sort       view
chgrp       doexec         gunzip      mknod     red            stty       ypdomainname
chmod       domainname     gzip        mktemp    rm             su         zcat
chown       echo           hostname    more      rmdir          sync
También podríamos haber puesto:
$ A="ls /bin"
$ B=`$A`
$ echo $B
arch ash ash.static awk basename bash bash2 bsh cat chgrp chmod chown consolechars cp cpio csh date dd df dmesg dnsdomainname doexec domainname echo ed egrep ex false fgrep gawk gawk-3.0.6 grep gtar gunzip gzip hostname igawk ipcalc kill ln loadkeys login ls mail mkdir mknod mktemp more mount mt mv netstat nice nisdomainname ping ps pwd red rm rmdir rpm rvi rview sed setserial sfxload sh sleep sort stty su sync tar tcsh touch true umount uname usleep vi view ypdomainname zcat
              

El operador $()

La shell bash proporciona el operador $() similar a las comillas invertidas. Ejecuta como orden los que haya entre paréntesis y devuelve su resultado. El mecanismo de funcionamiento es idéntico, con la ventaja de poder anidar operadores.