test y [ ]
[ condición ] es lo mismo que test condición. Es un comando, así que lleva espacios: [ -f "$1" ]
Archivos: -e existe · -f archivo · -d carpeta · -r -w -x permisos · -s no vacío
Texto: = igual · != distinto · -z vacío · -n no vacío
Números: -eq -ne -lt -le -gt -ge (=, ≠, <, ≤, >, ≥)
Unir: ! niega · [ a ] && [ b ] · [ a ] || [ b ] (o, dentro: -a y -o)
Bash tiene además [[ ]], más cómodo (admite && y patrones), pero [ ] funciona en cualquier shell.
Haz que el script muestre «Hola, mundo».
Se prueba con: ./reto.sh
Ver solución
#!/bin/bash
echo "Hola, mundo"
Un script es un archivo de texto con comandos. La primera línea, #!/bin/bash (shebang), dice qué programa lo ejecuta. Para lanzarlo: chmod +x script.sh y ./script.sh, o bash script.sh.
El script recibe un nombre y saluda: «./reto.sh Ana» → «Hola, Ana».
Se prueba con: ./reto.sh Ana, ./reto.sh Luis
Ver solución
#!/bin/bash
echo "Hola, $1"
$1…$9 son los argumentos (${10} a partir del 10). $0 es el nombre del script. Ponlos entre comillas: "$1", por si llevan espacios.
El script dice cuántos argumentos ha recibido: «Me has dado N argumentos».
Se prueba con: ./reto.sh, ./reto.sh uno, ./reto.sh a b c
Ver solución
#!/bin/bash
echo "Me has dado $# argumentos"
$# = número de argumentos. $@ = todos, cada uno por separado (úsalo como "$@"). $* = todos juntos en una sola cadena.
Si no le pasas ningún argumento, muestra «Uso: reto.sh NOMBRE» y termina con código 1. Si le pasas uno, «Hola, NOMBRE».
Se prueba con: ./reto.sh, ./reto.sh Ana
Ver solución
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Uso: reto.sh NOMBRE"
exit 1
fi
echo "Hola, $1"
if CONDICIÓN; then …; elif …; else …; fi. La condición es un comando: si da 0, se cumple. [ es un comando (como test) y por eso necesita espacios: [ $# -eq 0 ]. exit N termina el script con código N.
Recibe un nombre de archivo y dice «X existe» o «X no existe».
Se prueba con: ./reto.sh notas.txt, ./reto.sh nada.txt
Ver solución
#!/bin/bash
if [ -f "$1" ]; then
echo "$1 existe"
else
echo "$1 no existe"
fi
Pruebas de archivos: -e existe, -f es archivo, -d es carpeta, -r/-w/-x se puede leer/escribir/ejecutar, -s no está vacío. ! niega: [ ! -f x ].
Recibe un número y dice «par» o «impar».
Se prueba con: ./reto.sh 4, ./reto.sh 7, ./reto.sh 0
Ver solución
#!/bin/bash
if [ $(( $1 % 2 )) -eq 0 ]; then
echo par
else
echo impar
fi
Para números: -eq -ne -lt -le -gt -ge. Para texto: = y !=. [ 10 > 9 ] NO compara números: crea un archivo llamado 9. En bash también: (( n % 2 == 0 )).
Recibe una ruta y dice «archivo», «carpeta» o «no existe».
Se prueba con: ./reto.sh notas.txt, ./reto.sh logs, ./reto.sh nada
Ver solución
#!/bin/bash
if [ -f "$1" ]; then
echo archivo
elif [ -d "$1" ]; then
echo carpeta
else
echo "no existe"
fi
elif encadena condiciones: se ejecuta la primera que se cumpla.
Recibe una fruta: manzana o pera → «fruta de pepita»; fresa o cereza → «fruta roja»; cualquier otra → «no la conozco». Usa case.
Se prueba con: ./reto.sh manzana, ./reto.sh cereza, ./reto.sh kiwi
Ver solución
#!/bin/bash
case "$1" in
manzana|pera) echo "fruta de pepita" ;;
fresa|cereza) echo "fruta roja" ;;
*) echo "no la conozco" ;;
esac
case compara un valor con patrones (con comodines). Cada caso acaba en ;; y el bloque en esac (case al revés, como fi es if al revés).
Si el primer argumento es «start» muestra «Arrancando»; si es «stop», «Parando»; si no, «Uso: reto.sh start|stop» y termina con código 2.
Se prueba con: ./reto.sh start, ./reto.sh stop, ./reto.sh
Ver solución
#!/bin/bash
if [ "$1" = start ]; then
echo Arrancando
elif [ "$1" = stop ]; then
echo Parando
else
echo "Uso: reto.sh start|stop"
exit 2
fi
Así son los scripts de arranque de servicios (los antiguos de /etc/init.d). Las comillas en "$1" evitan errores cuando la variable está vacía o tiene espacios.
Recibe dos números y muestra el mayor (si son iguales, ese número).
Se prueba con: ./reto.sh 3 8, ./reto.sh 9 2, ./reto.sh 5 5
Ver solución
#!/bin/bash
if [ "$1" -ge "$2" ]; then
echo "$1"
else
echo "$2"
fi
-ge (mayor o igual) resuelve también el empate.
Recibe una nota de 0 a 10 y dice «suspenso» (menos de 5), «aprobado» (5 o 6), «notable» (7 u 8) o «sobresaliente» (9 o 10).
Se prueba con: ./reto.sh 3, ./reto.sh 5, ./reto.sh 6, ./reto.sh 8, ./reto.sh 9, ./reto.sh 10
Ver solución
#!/bin/bash
if [ "$1" -lt 5 ]; then
echo suspenso
elif [ "$1" -lt 7 ]; then
echo aprobado
elif [ "$1" -lt 9 ]; then
echo notable
else
echo sobresaliente
fi
Ordenar las condiciones ahorra comprobaciones: cada elif ya sabe que las anteriores fallaron.
7.12existe el usuarioscriptRecibe un nombre y dice «existe» o «no existe» según esté en etc/passwd.
Se prueba con: ./reto.sh ana, ./reto.sh pepe, ./reto.sh an
Ver solución
#!/bin/bash
if grep -q "^$1:" etc/passwd; then
echo existe
else
echo "no existe"
fi
Cualquier comando vale como condición: se cumple si termina con 0.
Si recibe exactamente 2 argumentos, los muestra al revés («b a»). Si no, muestra «Necesito 2 argumentos» y termina con código 1.
Se prueba con: ./reto.sh a b, ./reto.sh uno, ./reto.sh
Ver solución
#!/bin/bash
if [ $# -ne 2 ]; then
echo "Necesito 2 argumentos"
exit 1
fi
echo "$2 $1"
Comprobar los argumentos al principio y salir con error es lo primero que hace un buen script.
Recibe una ruta y dice «ejecutable» o «no ejecutable».
Se prueba con: ./reto.sh script.sh, ./reto.sh bin/ayudante, ./reto.sh notas.txt
Ver solución
#!/bin/bash
if [ -x "$1" ]; then
echo ejecutable
else
echo "no ejecutable"
fi
-r -w -x miran los permisos para TI (el usuario que ejecuta el script).
Si no recibe nada (o recibe un texto vacío) dice «vacío»; si no, «tiene N caracteres».
Se prueba con: ./reto.sh, ./reto.sh hola, ./reto.sh
Ver solución
#!/bin/bash
if [ -z "$1" ]; then
echo vacío
else
echo "tiene ${#1} caracteres"
fi
-z vacío · -n no vacío. Siempre con comillas: [ -z "$1" ].
Dice «número» si el primer argumento son solo dígitos, o «no es un número».
Se prueba con: ./reto.sh 42, ./reto.sh abc, ./reto.sh 4a, ./reto.sh 007
Ver solución
#!/bin/bash
if [[ "$1" =~ ^[0-9]+$ ]]; then
echo número
else
echo "no es un número"
fi
[[ =~ ]] usa expresiones regulares extendidas; la expresión va SIN comillas.
Recibe un nombre de archivo y dice qué es por su extensión: .txt «texto», .sh «script», .log «registro», cualquier otra «desconocido». Usa case.
Se prueba con: ./reto.sh notas.txt, ./reto.sh script.sh, ./reto.sh app.log, ./reto.sh foto.jpg
Ver solución
#!/bin/bash
case "$1" in
*.txt) echo texto ;;
*.sh) echo script ;;
*.log) echo registro ;;
*) echo desconocido ;;
esac
case es ideal para comparar con comodines.
Recibe una respuesta: s, S, y o Y → «sí»; n o N → «no»; otra cosa → «responde s o n».
Se prueba con: ./reto.sh s, ./reto.sh Y, ./reto.sh N, ./reto.sh quizá
Ver solución
#!/bin/bash
case "$1" in
s|S|y|Y) echo sí ;;
n|N) echo no ;;
*) echo "responde s o n" ;;
esac
[sSyY]) es un patrón con corchetes: cualquiera de esas letras.
Recibe un año y dice «bisiesto» o «no bisiesto» (divisible entre 4, salvo los divisibles entre 100 que no lo son entre 400).
Se prueba con: ./reto.sh 2024, ./reto.sh 2023, ./reto.sh 1900, ./reto.sh 2000
Ver solución
#!/bin/bash
a=$1
if [ $((a % 4)) -eq 0 ] && { [ $((a % 100)) -ne 0 ] || [ $((a % 400)) -eq 0 ]; }; then
echo bisiesto
else
echo "no bisiesto"
fi
(( )) permite escribir condiciones numéricas como en C: ==, !=, <, &&, ||.
Recibe un nombre: si la carpeta no existe la crea y dice «creada»; si existe, «ya existía».
Se prueba con: ./reto.sh logs, ./reto.sh nueva
Ver solución
#!/bin/bash
if [ -d "$1" ]; then
echo "ya existía"
else
mkdir "$1"
echo creada
fi
mkdir -p no falla si ya existe, pero aquí queremos avisar.
7.21código de salidascriptTermina con el código que reciba como argumento, sin mostrar nada.
Se prueba con: ./reto.sh 0, ./reto.sh 3, ./reto.sh 7
Ver solución
#!/bin/bash
exit $1
El código de salida es lo que ve quien llama al script (en $?).
Recibe dos textos y dice «iguales» o «distintos».
Se prueba con: ./reto.sh a a, ./reto.sh a b, ./reto.sh Hola hola
Ver solución
#!/bin/bash
if [ "$1" = "$2" ]; then
echo iguales
else
echo distintos
fi
Para texto = y != (en [[ ]] también ==). Distingue mayúsculas.
¿Qué comprueba [ -z "$1" ]?
- Que $1 es cero
- Que $1 está vacío
- Que $1 es un archivo
- Que $1 es un número
Ver solución
b) Que $1 está vacío
-z: longitud cero. -n: no vacío.
En [ ], ¿qué operador significa «menor o igual» para números?
Ver solución
-le
-lt < · -le ≤ · -gt > · -ge ≥ · -eq = · -ne ≠.
¿Cuál es la primera línea típica de un script de bash?
Ver solución
#!/bin/bash
También vale: #!/usr/bin/env bash
El shebang (#!) dice qué intérprete lo ejecuta: #!/bin/sh, #!/usr/bin/python3…
¿Qué variable contiene el número de argumentos de un script?
Ver solución
$#
$# número · $@ todos · $1… cada uno · $0 nombre del script · $? código del último comando.
¿Qué indica que un script termine con «exit 0»?
- Que todo fue bien
- Que hubo un error
- Que no hizo nada
- Que se ejecutará otra vez
Ver solución
a) Que todo fue bien
0 = todo bien; cualquier otro número (1-255) = algún error.
¿Con qué palabra se cierra un bloque case?
Ver solución
esac
if…fi, case…esac, do…done.
7.29espacios en [ ]pregunta¿Por qué «[$a = $b]» (sin espacios) falla?
- Porque falta comillas
- Porque = no existe
- Porque [ es un comando y necesita espacios
- No falla
Ver solución
c) Porque [ es un comando y necesita espacios
[ es un comando (test) y sus argumentos van separados por espacios; [$a sería otro nombre de comando.
¿Qué variable contiene el nombre del propio script?
Ver solución
$0
$0 es como se llamó al script (./reto.sh). basename "$0" da solo el nombre.
¿Qué hace «shift» en un script?
- Sale del script
- Borra todas las variables
- Cambia a mayúsculas
- Quita el primer argumento y corre los demás
Ver solución
d) Quita el primer argumento y corre los demás
Quita $1 y corre los demás: $2 pasa a ser $1, y $# baja en uno. Útil para recorrer opciones.
¿Qué muestra este código?
x=5
if [ $x -gt 3 ]; then echo grande; else echo pequeño; fi
Ver solución
grande
[ 5 -gt 3 ] se cumple: se ejecuta el then.
¿Qué muestra este código?
[ "abc" = "abc" ] && echo igual
Ver solución
igual
= compara texto; si son iguales, devuelve 0 y && ejecuta el echo.
7.34código de testpregunta¿Qué muestra este código?
[ 10 -lt 9 ]; echo $?
Ver solución
1
Una condición falsa devuelve 1.
¿Qué muestra este código?
test -z ""; echo $?
Ver solución
0
-z se cumple con un texto vacío: test devuelve 0.
¿Qué muestra este código?
[[ "hola" == h* ]] && echo empieza
Ver solución
empieza
[[ $x == h* ]] compara con un patrón (sin comillas en el patrón).
¿Qué muestra este código?
case "b.txt" in
*.sh) echo script ;;
*.txt) echo texto ;;
*) echo otro ;;
esacVer solución
texto
case prueba los patrones en orden y ejecuta el primero que encaja: *.txt.
¿Qué muestra este código?
set -- a b c
echo $#
Ver solución
3
set -- a b c es como haber llamado al script con a b c.
¿Qué muestra este código?
set -- a b c
shift
echo $1
Ver solución
b
Tras shift, $2 pasa a ser $1: b.
¿Qué muestra este código?
set -- "a b" c
for x in "$@"; do echo "[$x]"; done | head -n 1
Ver solución
[a b]
"$@" mantiene «a b» como un solo argumento: la primera vuelta imprime [a b].
7.41$* sin comillaspregunta¿Qué muestra este código?
set -- "a b" c
for x in $*; do echo "[$x]"; done | wc -l
Ver solución
3
$* y $@ sin comillas parten «a b» en dos: 3 vueltas. Por eso se usa "$@".
¿Qué muestra este código?
f() { return 3; }
f
echo $?Ver solución
3
return 3 pone el código de salida de la función, que $? recoge justo después.
7.43= con númerospregunta¿Qué muestra este código?
x=05
[ "$x" = 5 ] && echo texto-igual || echo texto-distinto
Ver solución
texto-distinto
Como texto, «05» y «5» son distintos.
¿Qué muestra este código?
x=05
[ "$x" -eq 5 ] && echo num-igual
Ver solución
num-igual
Como número, 05 vale 5.
¿Qué diferencia a [[ ]] de [ ]?
- Son iguales
- [[ ]] es propio de bash y admite patrones, =~, && y ||
- [ ] solo vale para números
- [[ ]] es más antiguo
Ver solución
b) [[ ]] es propio de bash y admite patrones, =~, && y ||
[[ ]] es de bash: no parte las variables por espacios, admite &&, ||, patrones (==) y expresiones regulares (=~). [ ] es el comando test, que funciona en cualquier shell POSIX.
¿Qué comprueba [ -s archivo ]?
- Que es un enlace
- Que es un socket
- Que existe y no está vacío
- Que es seguro
Ver solución
c) Que existe y no está vacío
Que existe y no está vacío.
¿Qué comprueba [ -e ruta ]?
- Que existe
- Que es ejecutable
- Que está vacío
- Que es igual
Ver solución
a) Que existe
Que existe (archivo, carpeta o lo que sea).
¿Con qué código termina un script que acaba con «exit» sin número?
- 0 siempre
- El del último comando ejecutado
- 1 siempre
- 255
Ver solución
b) El del último comando ejecutado
Con el código del último comando ejecutado.
¿Qué código de salida da la shell cuando el comando no existe?
Ver solución
127
127 = comando no encontrado · 126 = existe pero no se puede ejecutar · 128+N = muerto por la señal N (130 = Ctrl+C).
¿Y si el comando existe pero no tiene permiso de ejecución?
Ver solución
126
126 = encontrado pero no ejecutable (falta el permiso x o es una carpeta).
¿Cómo compruebas la sintaxis de script.sh sin ejecutarlo?
Ver solución
bash -n script.sh
bash -n solo lee y avisa de errores de sintaxis. shellcheck (si lo instalas) además avisa de malas prácticas.
¿Cómo ejecutas script.sh enseñando cada comando antes de ejecutarlo?
Ver solución
bash -x script.sh
Ideal para depurar: ves cada línea ya con las variables sustituidas.