Aprende leyendo en orden

Script de Shell - Argumentos y códigos de salida

Recibe los valores de ./a.sh foo bar con $1 $2 $@ $# $0, aporta un valor predeterminado con ${2:--}, comprueba $? y devuelve éxito o fallo con exit 0 / exit 1 — escribe y ejecuta un script práctico, ilustrado en una terminal del navegador.

Recibir argumentos — $1 / $2 / $0

Los scripts pueden tomar valores cuando los ejecutas.

Los valores que pones después del comando, como ./a.sh foo bar, se llaman argumentos, y dentro del script $1 es el primero y $2 es el segundo.

$0 es el nombre del propio script, $# es el número de argumentos pasados y $@ representa todos ellos en conjunto.

Con estos puedes ejecutar el script con una entrada distinta cada vez en lugar de con valores fijos.

SintaxisSignificadoEjemplo
$1 $2Primer y segundo argumentoecho "$1 then $2"
$0El nombre del propio scriptecho "running $0"
$#Número de argumentos pasadosecho "argc=$#"
$@Todos los argumentos en conjuntoecho "all: $@"
Cómo se asignan los argumentos
./a.sh foo bar$1 = foo$2 = bar$# = 2$@ = foo bar1.º2.ºconteotodos
Los valores que pasas van a $1 $2; $# da el conteo y $@ el conjunto completo.
set -- foo bar                   # fija parámetros posicionales para la demo
echo "1st: $1"                   # foo
echo "2nd: $2"                   # bar
echo "argc: $#"                  # 2
echo "all: $@"                   # foo bar

Escribe un script que reciba valores como argumentos y los imprima tal cual.

① Abre args.sh con vi args.sh, pulsa i para entrar en modo de inserción y pon #!/bin/sh en la primera línea.

② Escribe código que imprima el primer argumento ($1), el segundo ($2), el conteo ($#), todos los argumentos ($@) y el nombre del script ($0).

③ Pulsa Esc, guarda con :wq y luego añade permiso de ejecución.

④ Ejecútalo como ./args.sh foo bar con dos argumentos y comprueba qué valor fue a qué variable. Si te atascas, copia el cuerpo del panel de respuesta y pégalo en el modo de inserción de vi. (Ejecútalo correctamente y aparecerá la explicación).

Linux console
0 / 3 completado(s)
Loading Linux Terminal...

Aportar un valor predeterminado — ${1:-def}

A veces no se pasa ningún argumento.

Si escribes ${1:-default}, se usa default cuando $1 no está definido o está vacío, y se usa el valor dado cuando se proporciona uno.

Esto te permite escribir un script que sigue el argumento cuando se da, y funciona con un valor predeterminado seguro cuando no.

Comprobar $# también te dice si llegó el número esperado de argumentos.

SintaxisSignificadoEjemplo
${1:-def}Usa def cuando $1 no está definidoname=${1:-guest}
${2:-def}Usa def cuando $2 no está definidosep=${2:--}
Cómo se aporta el predeterminado
sep=${2:--}$2 = barsep = bar$2 está vacíosep = - (predeterminado)si se dasi se omiteTal como se daUsa el predeterminado
Con ${2:--}, pasar un segundo valor lo usa, y omitirlo usa el predeterminado -.
set --                           # reproduce la ejecución sin argumentos
echo "${1:-guest}"               # no definido, así que guest
set -- alice                     # ahora el primer argumento está fijado
echo "${1:-guest}"               # tiene un valor, así que alice

Escribe un script que reciba un separador como argumento y use un valor predeterminado cuando se omite.

① Abre format.sh con vi format.sh, pulsa i para entrar en modo de inserción y pon #!/bin/sh en la primera línea.

② Recibe el primer argumento como nombre de objetivo y el segundo como separador, pero escríbelo con ${2:-...} para que se use un predeterminado (por ejemplo -) cuando falte el segundo, y luego imprime el objetivo y el separador.

③ Pulsa Esc, guarda con :wq y luego añade permiso de ejecución.

④ Primero ejecútalo como ./format.sh foo, omitiendo el segundo argumento, y comprueba que el separador recurre al predeterminado. Si te atascas, copia el cuerpo del panel de respuesta y pégalo en el modo de inserción de vi.

Linux console
0 / 3 completado(s)
Loading Linux Terminal...

Devolver éxito o fallo — $? y exit N

Cuando un comando termina devuelve un código de salida, un número de 0 a 255.

Por convención 0 significa éxito y cualquier cosa distinta de 0 significa fallo.

Puedes leer el código de salida del comando anterior con $?.

Para grep es 0 cuando encuentra y 1 cuando no, así que el valor cambia según el resultado.

Desde dentro de un script fijas el código de salida explícitamente con exit N.

Devolver exit 0 para éxito y exit 1 para fallo es la convención común.

Quien lo llama recibe este valor a través de $? o && || y puede usarlo para controlar el flujo, como seguir solo cuando hay éxito.

Si omites exit, se devuelve tal cual el código de salida del último comando ejecutado.

SintaxisSignificadoEjemplo
$?Código de salida del comando anteriorgrep x f; echo $?
exit NTermina el script con el código de salida Nexit 1
Cómo fluyen los códigos de salida
El proceso tiene éxitoexit 0$? = 0El proceso fallaexit 1$? = 1devuelveleedevuelveleeÉxitoFallo
Un script devuelve exit 0 en caso de éxito y exit 1 en caso de fallo, y quien lo llama lee el resultado con $?.
printf 'apple\nbanana\n' > fruits.txt   # crea el material
grep apple fruits.txt > /dev/null
echo "found? $?"                          # encontrado, así que 0
grep mango fruits.txt > /dev/null
echo "found? $?"                          # no encontrado, así que 1

Escribe un script que busque en un archivo una palabra dada como argumento y devuelva un código de salida según el resultado.

① Abre search.sh con vi search.sh, pulsa i para entrar en modo de inserción y pon #!/bin/sh en la primera línea.

② En el script, crea un archivo de material y búscalo por la palabra recibida como primer argumento. Escribe código que imprima un mensaje de éxito y devuelva exit 0 cuando se encuentra, o imprima un mensaje de fallo y devuelva exit 1 cuando no.

③ Pulsa Esc, guarda con :wq y luego añade permiso de ejecución.

④ Ejecútalo como ./search.sh foo bar y luego comprueba el código de salida con echo $?. Si te atascas, copia el cuerpo del panel de respuesta y pégalo en el modo de inserción de vi.

Linux console
0 / 3 completado(s)
Loading Linux Terminal...

Procesar cada argumento por turno — $@ y $#

Cuando el número de argumentos no es fijo, en lugar de escribir $1 $2 uno por uno, recorre $@ con for para procesar tantos como se hayan pasado.

La forma for x in "$@"; do … done los toma de uno en uno, y mostrar el conteo con $# permite que el mismo script maneje cualquier número de argumentos.

Es un patrón común en herramientas que procesan varios archivos juntos.

SintaxisSignificadoEjemplo
"$@"Pasa cada argumento palabra por palabra (para for; necesita comillas dobles)for x in "$@"; do
$#Número de argumentos pasadosecho "count=$#"
Recorrer todos los argumentos
./a.sh foo bar baz$# = 3$@ = foo bar bazfor x in "$@"- foo- bar- bazconteotodosuno por unoimprimebucle con for
Obtén el conteo con $#, luego toma cada argumento de uno en uno con $@ en un bucle for para procesarlos.
set -- foo bar baz               # fija parámetros posicionales para la demo
echo "argc: $#"                  # 3
for x in "$@"; do
  echo "- $x"                    # - foo / - bar / - baz
done

Escribe un script que procese cada argumento pasado de uno en uno y que también muestre el conteo.

① Abre list.sh con vi list.sh, pulsa i para entrar en modo de inserción y pon #!/bin/sh en la primera línea.

② Imprime el número de argumentos con $#, luego toma cada uno por turno con $@ en un bucle for e imprime cada argumento en su propia línea.

③ Pulsa Esc, guarda con :wq y luego añade permiso de ejecución.

④ Ejecútalo como ./list.sh foo bar baz con tres argumentos y comprueba que el conteo y cada argumento se imprimen en orden. Si te atascas, copia el cuerpo del panel de respuesta y pégalo en el modo de inserción de vi.

Linux console
0 / 3 completado(s)
Loading Linux Terminal...
QUIZ

Verificación de conocimientos

Responde cada pregunta una a una.

Pregunta 1¿Qué entra en $2 cuando ejecutas ./a.sh foo bar?

Pregunta 2¿Cuál es el significado correcto de ${1:-guest}?

Pregunta 3¿Cuál lee el código de salida que indica si el comando anterior tuvo éxito?