Capítulo 4. Ejecutar comandos

Este trabajo se ha traducido utilizando IA. Agradecemos tus opiniones y comentarios: translation-feedback@oreilly.com

El objetivo principal de bash (o de cualquier shell) es permitirte interactuar con el sistema operativo del ordenador para que puedas realizar lo que necesites. Normalmente eso implica ejecutar programas, por lo que el intérprete de comandos toma los comandos que escribes, determina a partir de esa entrada qué programas deben ejecutarse y los ejecuta por ti.

Echemos un vistazo al mecanismo básico de lanzamiento de trabajos y exploremos algunas de las funciones que ofrece bash para lanzar programas en primer o segundo plano, secuencialmente o en paralelo, indicar si han tenido éxito, etc.

4.1 Ejecutar cualquier ejecutable

Problema

Necesitas ejecutar un comando en un sistema Linux o Unix.

Solución

Utiliza bash y escribe el nombre del comando en la línea de comandos:

$ someprog

Debate

Esto parece bastante sencillo, y en cierto modo lo es, pero pasan muchas cosas entre bastidores que nunca ves. Lo que es importante entender sobre bash es que su funcionamiento básico es cargar y ejecutar programas. Todo lo demás es sólo escaparate para prepararse para ejecutar programas. Claro, hay variables de shell y sentencias de control para hacer bucles y if/then/else bifurcación, y hay formas de controlar la entrada y la salida, pero todo esto es la guinda del pastel de la ejecución de programas.

Entonces, ¿de dónde saca el programa para ejecutarlo?

bash utiliza una variable del shell llamada $PATH para localizar tu ejecutable. La variable $PATH es una lista de directorios. Los directorios están separados por dos puntos (:). bash busca en cada uno de esos directorios un archivo con el nombre que hayas especificado. El orden de los directorios es importante: bash mira el orden en que aparecen los directorios en la variable y toma el primer ejecutable encontrado:

$ echo $PATH
/bin:/usr/bin:/usr/local/bin:.
$

En la variable $PATH que se muestra aquí, se incluyen cuatro directorios. El último directorio de la lista es un único punto (llamado directorio punto, o simplemente punto), que representa el directorio actual en un sistema de archivos Linux o Unix: estés donde estés, ése es el directorio al que se refiere punto. Por ejemplo, cuando copias un archivo de algún lugar a punto (es decir, cp /other/place/file . ), estás copiando el archivo en el directorio actual. Incluir el directorio punto en tu ruta le dice a bash que busque comandos no sólo en esos otros directorios, sino también en el directorio actual (.).

Mucha gente opina que poner dot en $PATH es un riesgo de seguridad demasiado grande: alguien podría engañarte y hacer que ejecutaras su propia versión maliciosa de un comando (por ejemplo, ls) en lugar de la que esperabas. Si el punto figurara en primer lugar, la versión de ls de otra persona sustituiría al comando ls normal, y podrías ejecutar ese comando sin saberlo. ¿No nos crees? Prueba con esto:

$ bash
$ cd
$ touch ls
$ chmod 755 ls
$ PATH=".:$PATH"
$ ls
$

De repente, parece que el ls no funciona en tu directorio personal. No obtienes ninguna salida. Si vas a otra ubicación (por ejemplo, cd /tmp), ls funcionará, pero no en tu directorio personal. ¿Por qué? Porque en ese directorio hay un archivo vacío llamado ls que se ejecuta (y no hace nada: está vacío) en lugar del comando ls normal ubicado en /bin/ls. Como hemos empezado este ejemplo ejecutando una nueva copia de bash, puedes salir de este lío saliendo de esta subshell, pero quizá quieras eliminar primero el falso comando ls:

$ cd
$ rm ls
$ exit
$

¿Puedes ver el peligro potencial de entrar en un directorio extraño con tu $PATH configurado para buscar en el directorio de puntos antes que en cualquier otro sitio?

Si pones el punto como último directorio en tu variable $PATH, al menos no te engañarán tan fácilmente. Por supuesto, si lo omites por completo, podría decirse que es incluso más seguro, y aún puedes ejecutar comandos en tu directorio local escribiendo un punto inicial y un carácter de barra oblicua, como en:

./myscript

La elección es tuya.

Advertencia

Nunca permitas directorios puntuales o con permisos de escritura en el $PATH de root. Para más información sobre este tema, consulta la Receta 14.9 y la Receta 14.10.

No olvides establecer permisos de ejecución en el archivo antes de invocar tu script:

chmod +x myscript

Sólo tienes que establecer los permisos una vez. A partir de entonces, puedes invocar el script como un comando.

Una práctica habitual entre algunos usuarios de bash es crear un directorio bin personal, análogo a los directorios del sistema /bin y /usr/bin donde se guardan los ejecutables. En tu bin personal (si lo creas en tu directorio personal, su ruta es ~/bin) puedes poner copias de tus shell scripts favoritos y otros comandos personalizados o privados. Luego añade ese directorio a tu $PATH, incluso al principio (PATH=~/bin:$PATH). De este modo, podrás seguir teniendo tus favoritos personalizados sin el riesgo de seguridad que supone ejecutar comandos de desconocidos.

4.2 Ejecutar varios comandos en secuencia

Problema

Necesitas ejecutar varios comandos, pero algunos tardan un rato y no quieres esperar a que termine cada uno antes de emitir el siguiente comando.

Solución

Hay tres soluciones a este problema, aunque la primera es bastante trivial: simplemente sigue escribiendo. Un sistema Linux o Unix es lo suficientemente avanzado como para permitirte teclear mientras trabaja en tus órdenes anteriores, así que puedes simplemente seguir tecleando una orden tras otra.

Otra solución bastante sencilla es escribir esos comandos en un archivo y luego decirle a bash que ejecute los comandos del archivo, es decir, un simple script de shell. Por ejemplo, supongamos que queremos ejecutar tres comandos, largo, medio y corto, cada uno de cuyos tiempos de ejecución se refleja en su nombre. Necesitamos ejecutarlos en ese orden, pero no queremos esperar a que termine el script largo antes de teclear los otros comandos. Podríamos utilizar un script de shell (también conocido como archivo por lotes). Aquí tienes una forma primitiva de hacerlo:

$ cat > simple.script
long
medium
short
^D                      # Ctrl-D, not visible
$ bash ./simple.script

La tercera solución, y posiblemente la mejor, es ejecutar cada comando en secuencia. Si quieres ejecutar cada programa independientemente de que fallen los anteriores, sepáralos con punto y coma:

long ; medium ; short

Si sólo quieres ejecutar el siguiente programa si el programa precedente funcionó, y todos los programas establecen correctamente los códigos de salida, sepáralos con dobles ampersands:

long && medium && short

Debate

El ejemplo de cat era sólo una forma muy primitiva de introducir texto en un archivo: redirigimos la salida del comando al archivo llamado simple.script (para saber más sobre cómo redirigir la salida, consulta el Capítulo 2). Es mejor que utilices un editor real, pero estas cosas son más difíciles de mostrar en ejemplos como éste. A partir de ahora, cuando queramos mostrar un script, nos limitaremos a mostrar el texto como texto incorpóreo no en una línea de comandos, o bien iniciaremos el ejemplo con un comando como cat filename para volcar el contenido del archivo a la pantalla (en lugar de redirigir la salida de nuestra escritura al archivo), y así mostrarlo en el ejemplo.

El objetivo principal de esta sencilla solución es demostrar que se puede poner más de un comando en la línea de comandos bash. En el primer caso, el segundo comando no se ejecuta hasta que sale el primero, el tercero no se ejecuta hasta que sale el segundo, y así sucesivamente, para tantos comandos como tengas en la línea. En el segundo caso, el segundo comando no se ejecuta a menos que el primero tenga éxito, el tercero no se ejecuta a menos que el segundo tenga éxito, y así sucesivamente, para tantos comandos como tengas en la línea.

Ver también

4.3 Ejecutar varios comandos a la vez

Problema

Necesitas ejecutar tres comandos, pero son independientes entre sí y no necesitan esperar a que se completen los anteriores.

Solución

Puedes ejecutar un comando en segundo plano poniendo un ampersand (&) al final de la línea de comandos. Así, podrías disparar los tres comandos en rápida sucesión de la siguiente manera:

$ long &
[1] 4592
$ medium &
[2] 4593
$ short
$

O mejor aún, puedes hacerlo todo en una sola línea de comandos:

$ long & medium & short
[1] 4592
[2] 4593
$

Debate

Cuando ejecutamos un comando "en segundo plano" (realmente no existe tal lugar en Linux), todo lo que eso significa en realidad es que desconectamos la entrada de teclado del comando y el shell no espera a que el comando se complete antes de dar otro prompt y aceptar más entrada de comando. La salida del comando (a menos que tomemos medidas explícitas para cambiar este comportamiento) seguirá llegando a la pantalla, por lo que en este ejemplo los tres comandos estarán intercalando salida en la pantalla.

Los bits impares de la salida numérica son el número de trabajo entre corchetes, seguido del ID del proceso del comando que acabamos de iniciar en segundo plano. En nuestro ejemplo, el trabajo 1 (proceso 4592) es el comando largo, y el trabajo 2 (proceso 4593) es el medio.

No pusimos short en segundo plano porque no pusimos un ampersand al final de la línea, así que bash esperará a que se complete antes de darnos el prompt del shell (el $).

El número de trabajo o ID de proceso se puede utilizar para proporcionar un control limitado sobre un trabajo. Por ejemplo, podríamos matar el trabajo largo con kill %1 (ya que su número de trabajo era 1), o podríamos especificar el número de proceso (es decir, kill 4592) con los mismos resultados mortales.

También puedes utilizar el número de trabajo para volver a conectarte a un trabajo en segundo plano. Por ejemplo, podríamos volver a conectar el trabajo largo al primer plano de con fg %1. Si sólo tienes un trabajo ejecutándose en segundo plano, ni siquiera necesitas el número de trabajo; basta con utilizar fg por sí mismo.

Consejo

Si ejecutas un comando y luego te das cuenta de que tardará en completarse más de lo que pensabas, puedes pausarlo utilizando Ctrl-Z, que te devolverá a un prompt. Entonces puedes escribir bg para desbloquear el trabajo y continuar ejecutándolo en segundo plano. Esto es básicamente añadir un & a posteriori.

4.4 Decir si una orden ha tenido éxito o no

Problema

Necesitas saber si la orden que has ejecutado ha tenido éxito.

Solución

La variable de shell $? se establece con un valor distinto de cero si el comando falla -siempre que el programador que escribió ese comando o script de shell siguiera la convención establecida:

$ somecommand
# it works...
$ echo $?
0
$ badcommand
# it fails...
$ echo $?
1
$

Debate

El estado de salida de un comando se guarda en la variable del shell referenciada con $?. Su valor puede oscilar entre 0 y 255. Cuando escribas un script de shell, es una buena idea que tu script salga con cero si todo va bien y con un valor distinto de cero si se encuentra una condición de error. Recomendamos utilizar sólo de 0 a 127 porque el shell utiliza 128+N para denotar la muerte por la señal N. Además, si utilizas un número mayor que 255 o menor que 0, los números se envolverán. Devuelve un estado de salida con la sentencia exit (por ejemplo, exit 1 o exit 0). Pero ten en cuenta que sólo tienes una oportunidad de leer el estado de salida de un comando:

$ badcommand
# it fails...
$ echo $?
1
$ echo $?
0
$

¿Por qué el segundo echo nos da como resultado 0? En realidad está informando sobre el estado del comando eco inmediatamente anterior. La primera vez que tecleamos echo $? nos devolvió un 1, que era el valor de retorno de badcommand. Pero el propio comando eco tiene éxito y, por tanto, el nuevo estado más reciente es éxito (es decir, un valor 0 ). Como sólo tienes una oportunidad de comprobar el estado de salida, muchos scripts de shell asignarán inmediatamente el estado a otra variable del shell, como en:

$ badcommand
# it fails...
$ STAT=$?
$ echo $STAT
1
$ echo $STAT
1
$

Podemos guardar el valor en la variable $STAT y comprobar su valor más adelante.

Aunque estamos mostrando esto en ejemplos de línea de comandos, el uso real de variables como $? se produce al escribir guiones. Normalmente puedes ver si un comando ha funcionado o no si estás viendo cómo se ejecuta en tu pantalla. Pero en un script, los comandos pueden estar ejecutándose sin supervisión.

Una de las grandes características de bash es que el lenguaje de programación es idéntico a los comandos que escribes en una ventana de terminal. Esto hace que sea mucho más fácil comprobar la sintaxis y la lógica mientras escribes tus guiones.

El estado de salida es más suele utilizarse en los scripts, y a menudo en las sentencias if, para realizar diferentes acciones en función del éxito o el fracaso de un comando. Aquí tienes un ejemplo sencillo por ahora, pero volveremos sobre este tema en futuras recetas:

somecommand
...
if (( $? )) ; then echo failed ; else echo OK; fi

(( )) evalúa una expresión aritmética; consulta las Recetas 6.1 y 6.2.

Tampoco recomendamos utilizar números negativos. El intérprete de comandos los aceptará sin error, pero no hará lo que esperas:

$ bash -c 'exit -2' ; echo $?
254

$ bash -c 'exit -200' ; echo $?
56

4.5 Ejecutar un comando sólo si otro comando ha tenido éxito

Problema

Necesitas ejecutar algunos comandos, pero sólo quieres ejecutar ciertos comandos si otros tienen éxito. Por ejemplo, te gustaría cambiar de directorio (mediante el comando cd ) a un directorio temporal y eliminar todos los archivos. Sin embargo, no quieres eliminar ningún archivo si cd falla (por ejemplo, si los permisos no te permiten entrar en el directorio, o si escribes mal el nombre del directorio).

Solución

Puedes utilizar el estado de salida ($?) del comando cd en combinación con una sentencia if para hacer el rm sólo si el cd tuvo éxito:

cd mytmp
if (( $? == 0 )); then rm * ; fi
Consejo

Una forma mejor de escribirlo es la siguiente, pero creemos que es más claro mostrarlo y explicarlo como lo hemos hecho:

if cd mytmp; then rm * ; fi

Debate

Obviamente, no necesitarías hacer esto si estuvieras escribiendo los comandos a mano. Verías cualquier mensaje de error del comando cd y, por tanto, no escribirías el comando rm. Pero el scripting es otra cosa, y esta prueba merece mucho la pena hacerla en un script como el de nuestro ejemplo para asegurarte de que no borras accidentalmente todos los archivos del directorio donde lo estás ejecutando.

Supongamos que ejecutas ese script desde el directorio equivocado, uno que no tenga un subdirectorio llamado mytmp. El cd fallaría, por lo que el directorio actual permanecería sin cambios. Sin la comprobación de if (por haber fallado el cd ) el script simplemente continuaría con la siguiente sentencia. Ejecutar el rm * eliminaría todos los archivos de tu directorio actual. Ouch. El if merece la pena.

Entonces, ¿cómo obtiene $? su valor? Es el código de salida del comando (ver Receta 4.4). Los programadores en lenguaje C lo reconocerán como el valor del argumento suministrado a la función exit(); por ejemplo, exit(4); devolvería un 4. Para el intérprete de comandos, un código de salida de cero se considera éxito y un valor distinto de cero significa fracaso.

Si escribes scripts bash, deberás asegurarte de establecer explícitamente los valores de retorno, para que $? se establezca correctamente desde tu script. Si no lo haces, el valor establecido será el valor del último comando ejecutado, que puede que no quieras como resultado.

4.6 Utilizar menos sentencias if

Problema

Como programador concienzudo, te tomaste muy a pecho lo que describimos en la receta anterior. Aplicaste el concepto a tu último script de shell, pero ahora te encuentras con que el script de shell es ilegible, con todas esas sentencias if comprobando el código de retorno de cada comando. ¿No existe una alternativa?

Solución

Utiliza el operador doble-ampersand en bash para proporcionar ejecución condicional:

cd mytmp && rm *

Debate

Al separar dos comandos mediante el doble ampersands, se le indica a bash que ejecute el primer comando y que ejecute el segundo sólo si el primero tiene éxito (es decir, si su estado de salida es 0). Esto es muy parecido a utilizar una sentencia if para comprobar el estado de salida del primer comando con el fin de proteger la ejecución del segundo comando:

cd mytmp
if (( $? == 0 )); then rm * ; fi

La sintaxis doble-ampersand pretende recordar al operador lógico AND del lenguaje C. Si conoces la lógica (y el lenguaje C), recordarás que si evalúas la expresión lógica A AND B, la expresión completa sólo puede ser verdadera si tanto la (sub)expresión A como la (sub)expresión B se evalúan como verdaderas. Si cualquiera de ellas es falsa, toda la expresión es falsa. El lenguaje C hace uso de este hecho, y cuando codifiques una expresión como if (A && B) { ... }, evaluará primero la expresión A. Si es falsa, ni siquiera se molestará en evaluar B ya que el resultado global (falso) ya ha sido determinado (por ser A falso).

¿Qué tiene que ver esto con bash? Bueno, si el estado de salida del primer comando (el que está a la izquierda de &&) es distinto de cero (es decir, ha fallado), no se molestará en evaluar la segunda expresión: no ejecutará el otro comando.

Si quieres ser minucioso en la comprobación de errores, pero no quieres que las sentencias if estén por todas partes, puedes hacer que bash salga cada vez que encuentre un fallo (es decir, un estado de salida distinto de cero) de cada comando de tu script (excepto en los bucles while y en las sentencias if, donde ya está capturando y utilizando el estado de salida) estableciendo en la bandera -e:

set -e
cd mytmp
rm *

Si activas la bandera -e, el shell saldrá cuando falle un comando. Si el cd de este ejemplo falla, el script saldrá y ni siquiera intentará ejecutar el comando rm *. Sin embargo, no recomendamos hacer esto en un intérprete de comandos interactivo, porque cuando el intérprete de comandos salga hará que tu ventana del intérprete de comandos desaparezca.

Ver también

4.7 Ejecutar trabajos largos sin supervisión

Problema

Ejecutaste un trabajo en segundo plano, luego saliste del intérprete de comandos y te fuiste a tomar un café. Cuando volviste a para comprobarlo, el trabajo ya no se estaba ejecutando y no se había completado. De hecho, tu trabajo no había avanzado mucho. Parece haberse detenido en cuanto saliste del intérprete de comandos.

Solución

Si quieres ejecutar un trabajo en segundo plano y esperas salir del intérprete de comandos antes de que finalice el trabajo, entonces necesitas nohupar el trabajo:

$ nohup long &
nohup: appending output to `nohup.out'
$

Debate

Cuando pones un trabajo en segundo plano (a través de &, como se describe en la Receta 4.3), sigue siendo un proceso hijo del intérprete de comandos bash. Cuando sales de una instancia del intérprete de comandos, bash envía una señal de suspensión (hup) a todos sus procesos hijos. Por eso tu trabajo no se ejecutó durante mucho tiempo. En cuanto saliste de bash, mató tu trabajo en segundo plano. (Oye, te ibas; ¿cómo iba a saberlo?)

El comando nohup simplemente configura el proceso hijo para que ignore las señales de colgado. Todavía puedes matar el trabajo con el comando kill, porque kill envía una señal SIGTERM, no una señal SIGHUP. Pero con nohup, bash no matará inadvertidamente tu trabajo cuando salgas.

El mensaje que da nohup sobre la adición de tu salida no es más que nohup intentando ser útil. Dado que es probable que salgas del intérprete de comandos después de emitir un comando nohup, es probable que tu destino de salida desaparezca; es decir, la sesión bash de tu terminal dejará de estar activa, por lo que el trabajo no podrá escribir en STDOUT. Y lo que es más importante, escribir en un destino inexistente provocaría un fallo. Así que nohup redirige la salida por ti, añadiéndola (no sobrescribiéndola, sino añadiéndola al final) a un archivo llamado nohup. out en el directorio actual. Puedes redirigir explícitamente la salida a otro lugar en la línea de comandos, y nohup es lo suficientemente inteligente como para detectar que esto ha ocurrido y no utilizar nohup.out para tu salida.

Ver también

4.8 Mostrar mensajes de error cuando se producen fallos

Problema

Necesitas que tu script de shell sea verboso sobre los fallos. Quieres ver mensajes de error cuando los comandos no funcionan, pero las sentencias if tienden a distraer del flujo visual de las sentencias.

Solución

Un lenguaje común entre algunos programadores de shell es utilizar || con comandos para escupir mensajes de depuración o error. He aquí un ejemplo:

cmd || printf "%b" "cmd failed. You're on your own\n"

Debate

De forma similar a como el && de la Receta 4.6 le dice a bash que no se moleste en evaluar la segunda expresión si la primera es falsa, el || le dice al intérprete de comandos que no se moleste en evaluar la segunda expresión si la primera es verdadera (es decir, tiene éxito). Al igual que &&, la sintaxis de || se remonta a la lógica y al lenguaje C, donde el resultado se determina (como verdadero) si la primera expresión de A OR B se evalúa como verdadera, por lo que no es necesario evaluar la segunda expresión. En bash, si la primera expresión devuelve 0 (es decir, tiene éxito), sigue adelante. Sólo si la primera expresión devuelve un valor distinto de cero (es decir, si el valor de salida del comando indica un fallo) debe evaluar la segunda parte y, por tanto, ejecutar el otro comando.

Advertencia: no te dejes engañar por esto:

cmd || printf "%b" "FAILED.\n" ; exit 1

¡La salida se ejecutará en cualquiera de los dos casos! El OR sólo está entre los dos primeros comandos. Si queremos que la salida sólo se produzca en caso de error, tenemos que agruparla con el printf para que ambos se consideren una unidad. La sintaxis deseada sería

cmd || { printf "%b" "FAILED.\n" ; exit 1 ; }

Ten en cuenta que es necesario el punto y coma después del último comando y justo antes de }, y que la llave de cierre debe estar separada por espacios en blanco del texto que la rodea. Para más información, consulta la Receta 2.14.

4.9 Ejecutar comandos desde una variable

Problema

Quieres ejecutar diferentes comandos en tu script dependiendo de las circunstancias. ¿Cómo puedes variar qué comandos se ejecutan?

Solución

Hay muchas soluciones a este problema: en eso consiste la programación de scripts. En los próximos capítulos hablaremos de varias construcciones de programación que se pueden utilizar para resolver este problema, como if/then/else, case declaraciones, y más. Pero he aquí un enfoque ligeramente distinto que revela algo sobre bash. Podemos utilizar el contenido de una variable (más sobre ellas en el Capítulo 5) no sólo para los parámetros, sino también para el propio comando:

FN=/tmp/x.x
PROG=echo
$PROG $FN
PROG=cat
$PROG $FN

Debate

Podemos asignar el nombre del programa a una variable (aquí utilizamos $PROG), y luego, cuando hagamos referencia a esa variable en el lugar donde se esperaría un nombre de comando, bash utilizará el valor de esa variable ($PROG) como comando a ejecutar. Analiza la línea de comandos, sustituye los valores de sus variables, y toma el resultado de todas las sustituciones y lo trata como la línea de comandos, como si se hubiera escrito así textualmente.

Advertencia

Ten cuidado con los nombres de variables que utilizas. Algunos programas, como InfoZip, utilizan variables de entorno como $ZIP y $UNZIP para pasar ajustes al propio programa, así que si haces algo como ZIP=/usr/bin/zip puedes pasarte días tirándote de los pelos preguntándote por qué funciona bien desde la línea de comandos, pero no en tu script. Confía en nosotros. Aprendimos esto por las malas. Además, RTFM.

Ver también

4.10 Ejecutar todos los scripts de un directorio

Problema

Quieres ejecutar una serie de guiones, pero la lista cambia continuamente; siempre estás añadiendo nuevos guiones, pero no quieres modificar continuamente una lista maestra.

Solución

Pon los scripts que quieras ejecutar en un directorio, y deja que bash ejecute todo lo que encuentre. En lugar de mantener una lista maestra, utiliza simplemente el contenido de ese directorio como lista maestra. Aquí tienes un script que ejecutará todo lo que encuentre en un directorio concreto:

for SCRIPT in /path/to/scripts/dir/*
do
    if [ -f "$SCRIPT" -a -x "$SCRIPT" ]
    then
        $SCRIPT
    fi
done

Debate

Discutiremos el bucle for y la sentencia if con más detalle en el Capítulo 6, pero esto te dará una idea. La variable $SCRIPT tomará valores sucesivos por cada archivo que coincida con el patrón comodín *, que coincide con todo lo que haya en el directorio nombrado (excepto los archivos de puntos invisibles, cuyos nombres empiezan por punto). Si se trata de un archivo (la prueba -f ) y tiene permisos de ejecución (la prueba -x ), el intérprete de comandos intentará ejecutar ese script.

En este sencillo ejemplo, no hemos proporcionado ninguna forma de especificar ningún argumento a los scripts mientras se ejecutan. Este sencillo script puede funcionar bien para tus necesidades personales, pero no se consideraría robusto; algunos podrían considerarlo francamente peligroso. Pero esperamos que te dé una idea de lo que te espera: algunas capacidades de scripting al estilo de los lenguajes de programación.

Ver también

  • Enel capítulo 6 encontrarás más información sobre los bucles for y las sentencias if

Get Libro de cocina bash, 2ª edición now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.