Shell scripts en Linux — ejercicios con parámetros que llevan espacios, notas que hay que validar y una lista de alumnos que corregir (y el archivo «3» que apareció en la carpeta)

Un lunes abrí la carpeta compartida del grupo de IC2 y había un archivo nuevo, vacío, que se llamaba 3. Nadie lo había creado. O eso creíamos. Lo borré, volví a lanzar mi script de resumen y… ahí estaba otra vez. El culpable era una línea que parecía inofensiva: if [ $correctas > 3 ]; then. Dentro de los corchetes, el > no compara: redirige. Bash creaba el archivo 3 y, de paso, la condición salía siempre verdadera.

Así son los scripts: lo que parece una comparación puede ser una redirección, lo que parece un parámetro pueden ser dos, y un $? mirado una línea tarde dice lo contrario de lo que pasó. En estos ejercicios vas a escribir tres scripts del corrector de prácticas y a cazar tres fallos de los que se cuelan en los scripts de verdad.

Cómo usar este artículo

  1. Lee el enunciado y la salida esperada de cada nivel. Esa salida es real: se ha obtenido ejecutando la solución una vez, como el usuario sergio, con LANG=C.
  2. Escribe tu script en una carpeta de pruebas con la misma estructura (entregas/ con ana.c, dani.c, laura.c, pablo.c y sergio.c, la práctica «suma» de la práctica). Usa la pista solo si te atascas.
  3. Haz los tres fragmentos de «¿Qué falla aquí?» prediciendo antes de mirar la explicación.
  4. Compara con las soluciones y quédate con el chuletario del final.

Nivel 1 (básico): información de varios archivos .c

Escribe info.sh, que recibe uno o más archivos .c como parámetros y, para cada uno, escribe cuántas líneas tiene y si contiene int main. Si un archivo no existe, lo dice y sigue con el siguiente. Sin parámetros, mensaje de uso por stderr y código 2. El script termina con código 0 si todos existen y tienen main, y 1 si no. Tiene que funcionar con nombres con espacios, como practica final.c (aquí, un archivo de una sola línea con un #include).

Salida esperada:

$ printf '#include <stdio.h>\n' > "practica final.c"
$ chmod +x info.sh
$ ./info.sh
Uso: ./info.sh archivo.c [archivo.c ...]
$ echo $?
2
$ ./info.sh entregas/ana.c "practica final.c" entregas/nadie.c
entregas/ana.c: 8 líneas, tiene main
practica final.c: 1 líneas, SIN main
entregas/nadie.c: no existe
$ echo $?
1
$ ./info.sh entregas/*.c
entregas/ana.c: 8 líneas, tiene main
entregas/dani.c: 8 líneas, tiene main
entregas/laura.c: 8 líneas, tiene main
entregas/pablo.c: 8 líneas, tiene main
entregas/sergio.c: 9 líneas, tiene main
$ echo $?
0

Recorre los parámetros con for f in "$@". Para contar líneas sin que salga el nombre, wc -l < "$f". Para saber si un archivo contiene un texto sin que se escriba nada, grep -q, y su código de salida en un if.

Nivel 2 (intermedio): calificaciones y media

Escribe notas.sh, que recibe un archivo con líneas alumno nota. Para cada línea, si la nota es un número del 0 al 10, escribe la calificación (Sobresaliente ≥ 9, Notable ≥ 7, Aprobado ≥ 5, Suspenso); si no, avisa de que no es válida y la salta. Al final, el número de notas válidas, de aprobados y de no válidas, y la media con un decimal. Código 2 si falta el parámetro, 1 si el archivo no existe o hay notas no válidas, y 0 si todo es correcto. El archivo notas.txt es:

ana 10
dani 5
laura 10
marta NP
pablo 0
sergio 10

Salida esperada:

$ chmod +x notas.sh
$ ./notas.sh notas.txt
ana: 10 Sobresaliente
dani: 5 Aprobado
laura: 10 Sobresaliente
marta: nota no válida (NP)
pablo: 0 Suspenso
sergio: 10 Sobresaliente
Notas válidas: 5. Aprobados: 4. No válidas: 1
Media: 7.0
$ echo $?
1
$ ./notas.sh notas.csv
No existe: notas.csv
$ echo $?
1

while read -r alumno nota; do … done < "$1" reparte cada línea en dos variables. Para saber si es una nota válida, un case con los patrones [0-9]|10). Y como bash solo hace cuentas con enteros, el decimal sale de suma * 10 / n y del resto % 10.

Nivel 3 (desafío): corregir a toda la lista

Escribe revisar_lista.sh lista carpeta: recorre alumnos.txt (ana, dani, laura, marta, pablo, ruben y sergio) y, para cada alumno, escribe su nota: NO ENTREGADO si no hay .c, 0 si no compila, 5 si compila pero su salida con entrada.txt no es esperado.txt, y 10 si es correcta. Nombre alineado en 8 columnas. Al final, cuántos hay en la lista, cuántos han entregado y cuántos están bien. Código 2 si los parámetros no son dos, 1 si alguien no ha entregado, 0 si todos han entregado.

Salida esperada:

$ chmod +x revisar_lista.sh
$ ./revisar_lista.sh alumnos.txt
Uso: ./revisar_lista.sh lista carpeta
$ echo $?
2
$ ./revisar_lista.sh alumnos.txt entregas
ana      10
dani     5
laura    10
marta    NO ENTREGADO
pablo    0
ruben    NO ENTREGADO
sergio   10
En la lista: 7. Entregadas: 5. Correctas: 3
$ echo $?
1

Haz una función nota_de que escriba la nota con echo y devuelva 1 solo si el alumno no ha entregado. Desde el bucle, nota=$(nota_de "$alumno") recoge el texto y, justo después, $? tiene su código. Para alinear, printf "%-8s %s\n".

¿Qué falla aquí?

Tres scripts cortos con un fallo cada uno. Antes de leer la explicación, predice qué escribe cada uno.

Fragmento 1: el aviso de uso que nunca avisa

#!/bin/bash
# uno.sh: avisa si no me pasan exactamente una carpeta
if [$# -ne 1]; then
    echo "Uso: $0 carpeta"
    exit 2
fi
echo "Corrijo la carpeta $1"

Lo lanzamos con una carpeta y sin nada. ¿Qué crees que pasa en cada caso? Esta es la salida real:

$ chmod +x uno.sh
$ ./uno.sh entregas
./uno.sh: line 3: [1: command not found
Corrijo la carpeta entregas
$ ./uno.sh
./uno.sh: line 3: [0: command not found
Corrijo la carpeta 

Bash ha leído [$# como una sola palabra. Tras sustituir $#, la orden que intenta ejecutar se llama [1 (o [0), que no existe: command not found. Ese error devuelve 127, que no es 0, así que el if va al else… que no existe, y el script sigue. Por eso, sin parámetros, escribe Corrijo la carpeta con un hueco: no ha avisado de nada.

Quitar los espacios de los corchetes. [ es una orden y ] su último parámetro: necesitan espacios, como cualquier orden y sus parámetros.

El arreglo es solo eso, dos espacios:

#!/bin/bash
# uno.sh: avisa si no me pasan exactamente una carpeta
if [ $# -ne 1 ]; then                 # espacio después de [ y antes de ]
    echo "Uso: $0 carpeta"
    exit 2
fi
echo "Corrijo la carpeta $1"

Y ahora sí:

$ chmod +x uno.sh
$ ./uno.sh entregas
Corrijo la carpeta entregas
$ ./uno.sh
Uso: ./uno.sh carpeta

Cuando veas command not found con un nombre raro que empieza por [, ya sabes qué buscar: un corchete pegado a lo que tiene al lado.

Fragmento 2: más de 3 con solo 2

#!/bin/bash
# comparar.sh: ¿han salido bien más de 3 prácticas?
correctas=2
if [ $correctas > 3 ]; then
    echo "Más de 3 correctas"
else
    echo "3 o menos"
fi

Con correctas=2, ¿debería escribir «3 o menos»? Esta es la salida real, y lo que hay en la carpeta después:

$ chmod +x comparar.sh
$ ./comparar.sh
Más de 3 correctas
$ ls
3
comparar.sh
$ cat 3

Escribe Más de 3 correctas y aparece un archivo llamado 3, vacío (por eso cat 3 no escribe nada). Es la anécdota del principio. Dentro de [ ], el > no es «mayor que»: es la redirección de siempre. Bash sustituye la variable, aparta el > 3, crea el archivo 3 para la salida de [ y ejecuta [ 2 ]. Con un solo parámetro, test comprueba si esa cadena no está vacía, y 2 no lo está: verdadero, código 0, then.

Por qué [ $correctas > 3 ] siempre da verdadero Lo esperado sería comparar 2 con 3 y obtener falso. En realidad bash sustituye la variable por 2, toma > 3 como una redirección que crea un archivo llamado 3, y deja [ 2 ], que es verdadero porque la cadena no está vacía. El arreglo es usar -gt. [ $correctas > 3 ] no compara: redirige if [ $correctas > 3 ]; then Lo que crees que pasa compara 2 > 3 → falso → escribe «3 o menos» Lo que hace bash 1. $correctas → 2 2. > 3: crea el archivo «3» 3. queda [ 2 ]: ¿cadena no vacía? → sí, $? = 0 → then «Más de 3 correctas» (y un archivo 3) Arreglo: [ «$correctas» -gt 3 ]
El > dentro de [ ] es el mismo > de las redirecciones: por eso aparece un archivo nuevo en la carpeta.

Comparar números con > o < dentro de [ ]. Para números, -gt, -lt, -ge, -le, -eq y -ne. Y dentro de [[ ]], > no redirige, pero compara cadenas: [[ 10 > 9 ]] es falso.

El arreglo usa -gt y, de paso, las comillas:

#!/bin/bash
# comparar.sh: ¿han salido bien más de 3 prácticas?
correctas=2
if [ "$correctas" -gt 3 ]; then       # -gt compara números; > dentro de [ ] redirige
    echo "Más de 3 correctas"
else
    echo "3 o menos"
fi

La salida ya es la correcta, y en la carpeta no aparece ningún 3:

$ chmod +x comparar.sh
$ ./comparar.sh
3 o menos
$ ls
comparar.sh

Fragmento 3: pablo compila (pero no)

#!/bin/bash
# compila.sh: dice si una entrega compila
gcc -Wall "$1" -o prog 2> /dev/null
echo "Compilación terminada"
if [ $? -eq 0 ]; then
    echo "Compila"
else
    echo "No compila"
fi

Le pasamos entregas/pablo.c, que no compila. Salida real:

$ chmod +x compila.sh
$ ./compila.sh entregas/pablo.c
Compilación terminada
Compila

Compila. ¿Cómo puede ser? Porque $? es el código de la última orden, y entre gcc y el if hay un echo. El if está mirando el código del echo, que siempre ha ido bien (0). El 1 de gcc se perdió en cuanto se ejecutó la orden siguiente.

Mirar $? una línea tarde. Cualquier orden, incluso un echo o un [ ], cambia $?.

Dos arreglos posibles: if gcc …; then directamente, o guardar el código en una variable justo después. Aquí usamos el segundo, porque queremos escribir el mensaje antes de decidir:

#!/bin/bash
# compila.sh: dice si una entrega compila
gcc -Wall "$1" -o prog 2> /dev/null
rc=$?                                 # guardamos el código JUSTO después de gcc
echo "Compilación terminada"
if [ "$rc" -eq 0 ]; then
    echo "Compila"
else
    echo "No compila"
fi

Con pablo y con ana:

$ chmod +x compila.sh
$ ./compila.sh entregas/pablo.c
Compilación terminada
No compila
$ ./compila.sh entregas/ana.c
Compilación terminada
Compila

Si vas a usar el código más de una vez, o hay algo entre la orden y la decisión, guárdalo siempre: rc=$? en la línea siguiente, y después trabaja con $rc.

Soluciones

Solución del nivel 1

#!/bin/bash
# info.sh: para cada archivo .c que recibe, cuenta sus líneas y mira si tiene main
# Uso: ./info.sh archivo.c [archivo.c ...]

if [ $# -eq 0 ]; then                 # sin parámetros no hay nada que mirar
    echo "Uso: $0 archivo.c [archivo.c ...]" >&2
    exit 2
fi
problemas=0
for f in "$@"; do                     # "$@": cada parámetro entero, aunque tenga espacios
    if [ ! -f "$f" ]; then
        echo "$f: no existe"
        problemas=$((problemas + 1))
        continue
    fi
    lineas=$(wc -l < "$f")            # con < wc solo escribe el número, sin el nombre
    if grep -q "int main" "$f"; then  # -q: callado; if solo mira el código de grep
        echo "$f: $lineas líneas, tiene main"
    else
        echo "$f: $lineas líneas, SIN main"
        problemas=$((problemas + 1))
    fi
done
[ "$problemas" -eq 0 ]                # 0 si todos existen y tienen main

Por qué está hecho así:

  • for f in "$@": es la única forma de que practica final.c llegue entero. Con $* o $@ sin comillas, el bucle intentaría mirar practica y final.c por separado, y dos de los resultados dirían no existe.
  • [ $# -eq 0 ] al principio: sin archivos no hay nada que hacer, así que mensaje de uso por stderr y exit 2 antes de entrar en el bucle.
  • continue en el caso de que no exista: avisa, cuenta el problema y pasa al siguiente. No tiene sentido contar las líneas de un archivo que no existe.
  • wc -l < "$f": con <, wc lee de su entrada y no sabe cómo se llama el archivo, así que solo escribe el número. Con wc -l "$f" saldría 8 entregas/ana.c y habría que recortarlo.
  • if grep -q "int main" "$f": grep devuelve 0 si encuentra el texto y 1 si no. La -q hace que no escriba la línea encontrada. Es el if de la teoría: no compara nada, mira un código.
  • El código final sale de [ "$problemas" -eq 0 ]. En la segunda llamada hay 2 problemas (practica final.c sin main y nadie.c, que no existe), así que devuelve 1. En la tercera, las cinco entregas tienen main: 0. Las líneas cuadran: los cuatro programas tienen 8 y el de sergio 9, por su int x; de más.

Sí, el script escribe «1 líneas». Arreglarlo es un buen extra: un if [ "$lineas" -eq 1 ] que elija entre «línea» y «líneas».

Solución del nivel 2

#!/bin/bash
# notas.sh: lee "alumno nota" de un archivo, pone la calificación y calcula la media
# Uso: ./notas.sh archivo

[ $# -eq 1 ] || { echo "Uso: $0 archivo" >&2; exit 2; }
[ -f "$1" ] || { echo "No existe: $1" >&2; exit 1; }

suma=0
n=0
aprobados=0
raras=0
while read -r alumno nota; do         # read reparte la línea: 1.ª palabra y el resto
    case "$nota" in
        [0-9]|10) ;;                  # un dígito o 10: es una nota válida, seguimos
        *)
            echo "$alumno: nota no válida ($nota)"
            raras=$((raras + 1))
            continue ;;
    esac
    if [ "$nota" -ge 9 ]; then        # -ge y no >: comparamos números
        palabra="Sobresaliente"
    elif [ "$nota" -ge 7 ]; then
        palabra="Notable"
    elif [ "$nota" -ge 5 ]; then
        palabra="Aprobado"
    else
        palabra="Suspenso"
    fi
    echo "$alumno: $nota $palabra"
    suma=$((suma + nota))
    n=$((n + 1))
    if [ "$nota" -ge 5 ]; then
        aprobados=$((aprobados + 1))
    fi
done < "$1"
echo "Notas válidas: $n. Aprobados: $aprobados. No válidas: $raras"
echo "Media: $((suma / n)).$(( (suma * 10 / n) % 10 ))"   # bash solo hace cuentas con enteros
[ "$raras" -eq 0 ]

Por qué está hecho así:

  • [ $# -eq 1 ] || { …; exit 2; }: las llaves agrupan varias órdenes para que el || ejecute las dos. Es un if de una línea, muy habitual al principio de los scripts.
  • read -r alumno nota: con dos variables, la primera palabra va a alumno y el resto a nota. Si alguna línea tuviera tres palabras, nota se quedaría con las dos últimas y el case la rechazaría.
  • El case va antes de cualquier -ge: si NP llegara a [ "$nota" -ge 9 ], saldría integer expression expected (lo viste con siete en la teoría). Primero se valida y después se compara. [0-9]|10) encaja con un solo dígito o con 10; 11, -3 o NP van al *).
  • -ge y no >: comparamos números. Con > dentro de [ ] crearíamos archivos con nombre de nota.
  • La media: notas válidas 10 + 5 + 10 + 0 + 10 = 35, y 35 / 5 = 7. La parte entera es $((35 / 5)) = 7 y el decimal, (35 × 10 / 5) % 10 = 70 % 10 = 0. De ahí 7.0. Si la suma fuera 36: 36 / 5 = 7 y 360 / 5 = 72, 72 % 10 = 2, o sea 7.2, que es 36 / 5 = 7,2.
  • Los aprobados: ana, dani, laura y sergio tienen 5 o más; pablo no. 4 aprobados, y marta no cuenta porque su nota no es válida.
  • El exit final es la comparación [ "$raras" -eq 0 ]: hay una nota rara, así que devuelve 1. Con notas.csv, que no existe, la segunda comprobación corta antes de leer nada y también devuelve 1.

Dividir entre n sin pensar en el caso n = 0. Si el archivo no tuviera ninguna nota válida, $((suma / n)) daría division by 0. Un if [ "$n" -eq 0 ] antes de la media lo evita.

Solución del nivel 3

#!/bin/bash
# revisar_lista.sh: corrige a todos los de la lista, hayan entregado o no
# Uso: ./revisar_lista.sh lista carpeta

if [ $# -ne 2 ]; then
    echo "Uso: $0 lista carpeta" >&2
    exit 2
fi
lista=$1
carpeta=$2

nota_de() {                           # nota_de ALUMNO: escribe su nota (o el motivo)
    local fuente="$carpeta/$1.c"
    local binario="$carpeta/$1"
    if [ ! -f "$fuente" ]; then
        echo "NO ENTREGADO"
        return 1
    fi
    rm -f "$binario"
    if ! gcc -Wall "$fuente" -o "$binario" 2> /dev/null; then
        echo "0"
        return 0
    fi
    if [ "$("$binario" < entrada.txt)" = "$(cat esperado.txt)" ]; then
        echo "10"
    else
        echo "5"
    fi
}

en_lista=0
entregadas=0
correctas=0
while read -r alumno; do
    en_lista=$((en_lista + 1))
    nota=$(nota_de "$alumno")         # $( ) recoge lo que la función escribe
    if [ $? -eq 0 ]; then             # justo después: el $? es el de nota_de
        entregadas=$((entregadas + 1))
    fi
    if [ "$nota" = "10" ]; then
        correctas=$((correctas + 1))
    fi
    printf "%-8s %s\n" "$alumno" "$nota"   # %-8s: nombre a la izquierda en 8 columnas
done < "$lista"
echo "En la lista: $en_lista. Entregadas: $entregadas. Correctas: $correctas"
[ "$entregadas" -eq "$en_lista" ]

Por qué está hecho así:

  • La función escribe y devuelve cosas distintas. echo manda la nota a stdout (la recoge $( )) y return 1 marca el caso «no entregado». Así, con una sola llamada sabemos la nota y si cuenta como entregada.
  • if [ $? -eq 0 ] va justo después de nota=$(nota_de …): una asignación con $( ) deja en $? el código de lo que se ejecutó dentro. Si pusiéramos algo en medio, perderíamos el código (el fragmento 3).
  • return 0 cuando no compila: el alumno sí ha entregado, aunque se lleve un 0. Solo NO ENTREGADO devuelve 1.
  • rm -f antes de compilar, por la misma razón que en la práctica: que un ejecutable viejo no apruebe por nadie.
  • printf "%-8s %s\n": %-8s escribe el nombre a la izquierda y rellena con espacios hasta 8 columnas. echo no sabe alinear.
  • Las cuentas: 7 alumnos en la lista; entregan 5 (todos menos marta y ruben, 7 − 2 = 5); correctas las de 10: ana, laura y sergio, 3. Como 5 ≠ 7, la última comparación devuelve 1.
El informe del nivel 3 Resultado real del nivel 3: ana, laura y sergio sacan 10; dani 5 porque compila pero da otra salida; pablo 0 porque no compila; marta y ruben no han entregado. En total, 7 en la lista, 5 entregadas y 3 correctas, y el script termina con código 1. revisar_lista.sh alumnos.txt entregas ana 10 dani 5 · compila, salida mal laura 10 marta NO ENTREGADO · return 1 pablo 0 · no compila ruben NO ENTREGADO · return 1 sergio 10 En la lista 7 Entregadas 5 Correctas 3 entregadas ≠ en la lista $? = 1
Los «NO ENTREGADO» no cuentan como entregadas gracias al return 1 de nota_de.

Pruébalo en tu terminal

La trampa del fragmento 2, en directo y sin script, para que la veas en tres órdenes. Tecléalo en una carpeta vacía:

$ correctas=2
$ [ $correctas > 3 ] && echo "mayor que 3"
mayor que 3
$ ls
3
$ [ "$correctas" -gt 3 ] && echo "mayor que 3" || echo "no es mayor que 3"
no es mayor que 3
$ rm 3
$ [[ $correctas > 10 ]] && echo "cadena: 2 va después de 10"
cadena: 2 va después de 10

Qué observar:

  1. [ $correctas > 3 ] && echo "mayor que 3" escribe mayor que 3 aunque 2 no es mayor que 3.
  2. El ls siguiente enseña el archivo 3 recién creado: es la prueba de que el > ha redirigido.
  3. Con -gt, la misma comparación sale falsa y el || escribe no es mayor que 3.
  4. La última línea es la trampa de [[ ]]: ahí > compara cadenas, y "2" va después de "10" en el orden del diccionario (el 2 va después del 1), así que «2 > 10» sale verdadero.

Chuletario: shell scripts en Linux

Lo esencial en 30 segundos

  • Primera línea #!/bin/bash, chmod +x una vez y ./script.sh.
  • Variables sin espacios en el = y siempre entre comillas dobles al usarlas: "$x".
  • Parámetros: $1… $#, y "$@" para recorrerlos.
  • if mira el código de salida (0 = bien). [ ] es una orden: espacios dentro.
  • Números con -eq -ne -lt -le -gt -ge y $(( )); cadenas con = y !=.
  • Errores por stderr (>&2) y exit con un código que signifique algo.

Quiero… / Código / Resultado

Quiero…CódigoResultado
Guardar la salida de una ordenn=$(ls entregas | wc -l)n vale 5
Usar una variable pegada a texto"${alumno}_v2.c"laura_v2.c
Un parámetro con valor por defectocarpeta=${1:-entregas}entregas si no hay $1
Quitar la extensiónbasename entregas/ana.c .c o ${f%.c}ana / entregas/ana
Comprobar el número de parámetros[ $# -eq 1 ] || usouso si no hay exactamente 1
Saber si un archivo existe[ -f "$f" ]código 0 si existe
Saber si un archivo tiene algo[ -s "$f" ]código 0 si no está vacío
Buscar un texto sin escribirlogrep -q "int main" "$f"código 0 si lo encuentra
Comparar dos archivoscmp -s a bcódigo 0 si son idénticos
Hacer una cuenta$((suma / n))entero: 7 / 2 = 3
Leer un archivo línea a líneawhile read -r a b; do … done < fa = 1.ª palabra, b = resto
Quitar la opción ya leídashift$2 pasa a ser $1
Alinear columnasprintf "%-8s %s\n" "$a" "$b"nombre en 8 columnas
Ver qué ejecuta el scriptbash -x script.shcada orden con +
Comprobar la sintaxisbash -n script.shcódigo 0 si está bien

Plantillas de los ejercicios

EjercicioEsqueletoResultado con nuestros datos
Nivel 1for f in "$@"; do [ -f "$f" ] || continue; …; done5 entregas con main, código 0
Nivel 2while read -r a n; do case "$n" in [0-9]|10) ;; *) continue ;; esac; …; done < "$1"Media 7.0, 4 aprobados, código 1
Nivel 3nota=$(nota_de "$a"); if [ $? -eq 0 ]; then …; fi7 en la lista, 5 entregadas, 3 correctas, código 1

Síntoma / Causa probable

SíntomaCausa probable
Permission denied al lanzar ./script.shFalta chmod +x
script.sh: command not foundFalta el ./ delante
x: command not found en una asignaciónEspacios alrededor del =
[1: command not foundFalta el espacio después de [
Aparece un archivo con nombre de número> o < dentro de [ ]
integer expression expected-eq, -gt… con algo que no es un número
Un nombre con espacio se parte en dosVariable sin comillas o $* en lugar de "$@"
if decide al revés$? mirado tarde, o un exit 1 cuando todo fue bien
$? da 0 tras una tubería que fallóEs el código de la última orden de la tubería (PIPESTATUS)
El script se queda paradoUn programa o un read esperan datos del teclado: falta un <

Antes de entregar, pregúntate

  1. ¿Comprueba el script sus parámetros al principio y termina con exit 2 y un mensaje por stderr si lo llaman mal?
  2. ¿Están todas las variables entre comillas dobles y recorres los parámetros con "$@"?
  3. ¿Comparas números con -eq, -gt… y cadenas con =?
  4. ¿Devuelve el script 0 solo cuando todo ha ido bien? Compruébalo con echo $? después de cada caso.

Con esto cierras los shell scripts de IC2. Si quieres repasar, vuelve a la teoría o a la práctica. Lo siguiente del Linux de IC2 será vi y la configuración de red.

Sigue aprendiendoTodos los artículos de Linux

¿Te ha servido este artículo? Así puedes apoyar SergioLearns →

Sigue aprendiendo

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *