Módulo 5: Máquinas remotas, redes y scripting
6. Tu primer script de shell
Descripción
Al final de esta lección vas a poder tomar una secuencia de comandos que ya escribiste a mano dos o tres veces y convertirla en un archivo .sh propio: con un shebang portable, el permiso de ejecución correcto, variables que no se rompen con un espacio de más, comillas que expanden lo que quieres y protegen lo que no, parámetros que tu script recibe desde la línea de comandos, una forma de pedirle un dato al usuario cuando lo necesitas, y una salida controlada con echo o printf.
Esto es exactamente lo que separa a alguien que "sabe usar la terminal" de alguien que la usa para construir herramientas. Cada vez que conectas a un servidor con ssh, corres un rsync con las mismas cinco banderas, y después revisas la fecha y quién eres — y lo repites la semana siguiente tecleando línea por línea de nuevo — tienes un candidato perfecto para un script. Un script no es solo "ahorrarte tecleo": es un procedimiento que puedes compartir con un compañero de equipo, versionar en Git, y confiar en que hace exactamente lo mismo la décima vez que la primera.
Conexión con el módulo: en la lección anterior resolviste el problema de que un proceso remoto muera al cerrar tu laptop — tmux y nohup te dieron persistencia. Hoy resuelves un problema distinto: dejas de teclear la misma secuencia de comandos a mano cada vez y la conviertes en un archivo reproducible. El script que escribes hoy corre de arriba hacia abajo, en línea recta, sin tomar ninguna decisión todavía — eso es exactamente lo que llega en la próxima lección, con if, bucles y códigos de salida propios.
De la tubería repetida al archivo ejecutable
Piensa en la diferencia entre explicarle una receta a alguien de memoria, en voz alta, cada vez que la cocina — y arriesgarte a olvidar un paso o cambiar el orden por accidente — frente a escribirla una sola vez en una tarjeta que cualquiera puede seguir exactamente igual, hoy y dentro de un año. Un script de shell es esa tarjeta: los mismos comandos que ya tecleaste, guardados en un archivo, en el mismo orden, listos para correr con un solo golpe de comando.
Todo script bash empieza con una línea especial llamada shebang: #! seguido de la ruta al intérprete que debe ejecutarlo. Cuando el sistema operativo ve que un archivo empieza con #!, no adivina qué hacer con el resto del archivo — lee esa primera línea y le entrega el archivo completo al programa que ahí se indica. Vas a escribir esa línea así, siempre, en todos tus scripts bash:
#!/usr/bin/env bash
Y no así, aunque también funcione en muchos sistemas:
#!/bin/bash
La diferencia importa más de lo que parece. #!/bin/bash asume que bash vive exactamente en /bin/bash, algo cierto en la mayoría de las distribuciones Linux, pero no universal. #!/usr/bin/env bash, en cambio, le pide a env que busque bash recorriendo tu variable PATH y use la primera que encuentre — el mismo mecanismo de búsqueda que usa la terminal cuando tecleas bash a secas. Esto importa especialmente en macOS: Apple congeló el /bin/bash del sistema en la versión 3.2 desde hace más de una década (la última versión con la licencia GPLv2; las versiones más nuevas de bash usan GPLv3, y Apple no la distribuye). Si instalas una versión moderna de bash con Homebrew, esa versión nueva queda en otra ruta (típicamente /opt/homebrew/bin/bash), y solo #!/usr/bin/env bash la va a encontrar primero, porque Homebrew coloca esa ruta al inicio de tu PATH. Con #!/bin/bash fijo, tu script sigue corriendo con la bash antigua del sistema aunque tengas una más nueva instalada.
Ejemplo trabajado
Imagina que ya corriste estos tres comandos, uno por uno, para revisar en qué máquina estás:
whoami
hostname
date
Qué esperar (los valores exactos van a variar según tu máquina):
alex
alexs-macbook.local
Tue Jul 21 09:14:32 -05 2026
Ahora convierte esos tres comandos en un archivo. Créalo con tu editor o con printf:
printf '%s\n' \
'#!/usr/bin/env bash' \
'# server-info.sh - imprime quién eres, en qué máquina y cuándo, de un vistazo.' \
'' \
'whoami' \
'hostname' \
'date' \
> server-info.sh
Dale permiso de ejecución (esto retoma chmod de la lección 3 del módulo anterior) y corre el script:
chmod +x server-info.sh
./server-info.sh
Qué esperar:
alex
alexs-macbook.local
Tue Jul 21 09:14:32 -05 2026
Mismo resultado que tecleando los tres comandos a mano — pero ahora es un archivo que puedes correr con un solo comando, compartir con alguien más, o guardar en un repositorio.
Tres formas de correr el mismo archivo
chmod +x no es un detalle decorativo: es lo que le permite al sistema operativo tratar tu archivo como un programa en vez de como texto plano, y conecta directo con lo que ya viste sobre el bit x en la lección de permisos. Pero el permiso de ejecución no es la única forma de correr un script, y vale la pena distinguir las tres que te vas a encontrar.
| Forma | Qué necesita | Qué usa |
|---|---|---|
./script.sh | Permiso de ejecución (x) en el archivo | Lee el shebang y le entrega el archivo a ese intérprete |
bash script.sh | Solo permiso de lectura | Ignora el shebang por completo — tú ya elegiste el intérprete al escribir bash |
sh script.sh | Solo permiso de lectura | Corre el archivo con sh, que en muchos sistemas Linux (Debian, Ubuntu) no es bash sino dash, un shell más limitado |
La fila de sh no es un detalle menor: si tu script usa características propias de bash (como las que vas a ver en esta misma lección) y alguien lo corre con sh script.sh en un sistema donde sh es dash, algunas cosas van a fallar o comportarse distinto, sin que el shebang de tu archivo tenga ninguna oportunidad de evitarlo — porque sh script.sh decide el intérprete antes de que el shebang se lea.
Ejemplo trabajado
Quítale el permiso de ejecución al script que acabas de crear y observa qué falla y qué no:
chmod 644 server-info.sh
./server-info.sh
Qué esperar:
-bash: ./server-info.sh: Permission denied
Sin el bit x, el sistema se niega incluso a intentarlo. Pero invocarlo explícitamente con bash sigue funcionando, porque solo necesita poder leer el archivo:
bash server-info.sh
Qué esperar:
alex
alexs-macbook.local
Tue Jul 21 09:14:32 -05 2026
Devuélvele el permiso de ejecución para seguir usándolo como en el resto de la lección:
chmod +x server-info.sh
Variables: asignación sin espacios y las comillas que sí importan
Una variable en bash guarda un valor con un nombre que puedes reutilizar. La sintaxis es rígida en un punto que sorprende a casi todo el mundo la primera vez: nunca lleva espacios alrededor del =.
user_name="Alex" # correcto
user_name = "Alex" # error
La segunda línea falla porque bash no ve una asignación: ve el comando user_name, seguido de los argumentos = y Alex. Bash intenta ejecutar un programa llamado user_name, no lo encuentra, y te devuelve command not found. Sin espacios, bash reconoce el patrón nombre=valor como asignación; con un espacio de por medio, deja de reconocerlo como tal.
Para leer el valor guardado, antepones $ al nombre ($user_name, o ${user_name} cuando necesitas dejar claro dónde termina el nombre, por ejemplo antes de pegarle texto sin espacio: ${user_name}_backup). Y aquí entra la parte que de verdad importa: casi todas las referencias a variables deben ir entre comillas dobles. Las comillas dobles expanden variables y sustituciones de comando, pero tratan el resultado como una sola pieza de texto, espacios incluidos. Sin comillas, bash vuelve a partir ese valor en palabras separadas dondequiera que encuentre un espacio — el mismo mecanismo que separa los argumentos que tecleas en la terminal.
Las comillas simples son más estrictas todavía: no expanden absolutamente nada, ni variables ni sustituciones. Todo dentro de comillas simples es texto literal, carácter por carácter.
Ejemplo trabajado
Crea un archivo con un espacio en el nombre — un caso más común de lo que parece (reportes exportados, archivos descargados del navegador):
file_name="my report.txt"
touch "$file_name"
ls
Qué esperar:
my report.txt
Un solo archivo, con el espacio incluido en el nombre, exactamente como esperabas. Ahora repite el mismo touch sin las comillas:
rm "my report.txt"
touch $file_name
ls
Qué esperar:
my report.txt
Dos archivos: my y report.txt. Sin comillas, bash partió el valor de $file_name en dos palabras porque encontró un espacio adentro, y touch recibió dos argumentos en vez de uno. Limpia antes de seguir: rm my report.txt.
Ahora compara comillas dobles contra simples con la misma variable:
echo "Hola, $user_name"
echo 'Hola, $user_name'
Qué esperar:
Hola, Alex
Hola, $user_name
La comilla doble expandió $user_name a su valor. La comilla simple lo dejó tal cual, texto literal — ni siquiera reconoció que ahí había una variable.
Capturar la salida de un comando: sustitución con $( )
Hasta ahora tus scripts solo imprimen la salida de un comando directamente en pantalla. Pero muchas veces quieres guardar esa salida en una variable, para usarla después — en un mensaje, en un nombre de archivo, en lo que sea. Para eso existe la sustitución de comandos: $(comando) se reemplaza por lo que ese comando imprime en su salida estándar, sin el salto de línea final.
today="$(date +%F)"
Vas a ver también la sintaxis antigua con comillas invertidas (`comando`), que hace lo mismo, pero $( ) es la forma preferida hoy: se anida sin ambigüedad ($(echo "hoy: $(date +%F)") funciona sin trucos), mientras que anidar comillas invertidas dentro de otras comillas invertidas requiere escapar caracteres y se vuelve difícil de leer.
Ejemplo trabajado
Guarda en variables el resultado de tres comandos distintos y combínalos en un solo mensaje:
today="$(date +%F)"
user_name="$(whoami)"
host_name="$(hostname)"
echo "$user_name se conectó a $host_name el $today"
Qué esperar:
alex se conectó a alexs-macbook.local el 2026-07-21
Cada $( ) corrió su comando por separado, capturó el texto que imprimió, y bash lo insertó en el lugar exacto donde escribiste la sustitución — igual que si hubieras escrito el valor a mano, pero calculado en el momento en que el script corre.
Parámetros posicionales: qué recibe tu script desde la línea de comandos
Un script se vuelve mucho más útil cuando no tiene todo escrito a fuego adentro, sino que recibe información de quien lo llama. Bash guarda automáticamente los argumentos que le pasaste al invocar el script en variables especiales llamadas parámetros posicionales:
| Parámetro | Qué contiene |
|---|---|
$0 | El nombre con el que se invocó el script (por ejemplo, ./server-info.sh) |
$1, $2, $3… | El primer argumento, el segundo, el tercero — en el orden en que los escribiste |
$# | La cantidad total de argumentos recibidos |
$@ | Todos los argumentos, cada uno como una palabra separada |
"$@" (entre comillas dobles) es la forma que casi siempre quieres cuando necesitas reenviar los argumentos completos a otro comando más adelante: preserva cada argumento como su propia palabra, incluso si alguno tiene espacios adentro — el mismo cuidado con las comillas que ya viste con variables normales, aplicado a un grupo entero de valores.
Ejemplo trabajado
Crea un script que solo reporta lo que recibió, sin hacer nada más con esa información todavía:
printf '%s\n' \
'#!/usr/bin/env bash' \
'# args-demo.sh - muestra qué te llega desde la línea de comandos.' \
'' \
'echo "Nombre del script: $0"' \
'echo "Primer argumento: $1"' \
'echo "Cantidad de argumentos: $#"' \
'echo "Todos los argumentos: $@"' \
> args-demo.sh
chmod +x args-demo.sh
./args-demo.sh production alex 42
Qué esperar:
Nombre del script: ./args-demo.sh
Primer argumento: production
Cantidad de argumentos: 3
Todos los argumentos: production alex 42
$1 tomó exactamente la primera palabra que escribiste después del nombre del script (production), sin que tuvieras que pedírselo — bash ya los había separado y guardado antes de que tu script empezara a correr.
Entrada interactiva con read
Los parámetros posicionales sirven cuando quien llama al script ya sabe qué argumentos darle. Pero a veces quieres pedirle un dato al usuario en el momento, mientras el script corre — sin obligarlo a memorizar el orden de los argumentos. Para eso existe el comando read: lee una línea de la entrada estándar y la guarda en la variable que le indiques.
read -r -p "¿Cuál es tu nombre? " user_name
La bandera -p muestra el texto entre comillas como aviso, en la misma línea donde el usuario va a escribir, sin necesidad de un echo aparte antes. La bandera -r (de raw) es una buena costumbre casi siempre: sin ella, read trata la barra invertida (\) como carácter de escape dentro de lo que el usuario tecleó, algo que casi nunca es lo que quieres cuando simplemente estás pidiendo un nombre o una ruta.
Ejemplo trabajado
printf '%s\n' \
'#!/usr/bin/env bash' \
'# ask-name.sh - pide un dato al usuario en vez de recibirlo como argumento.' \
'' \
'read -r -p "¿Cuál es tu nombre? " user_name' \
'echo "Hola, $user_name"' \
> ask-name.sh
chmod +x ask-name.sh
./ask-name.sh
Qué esperar (el script se detiene y espera que escribas algo; aquí se muestra lo que tecleaste después del aviso):
¿Cuál es tu nombre? Alex
Hola, Alex
El script se quedó pausado exactamente en la línea de read, hasta que tecleaste Alex y presionaste Enter. A partir de ahí, $user_name guarda ese valor igual que si lo hubieras asignado con =.
echo frente a printf
echo es el comando más simple para imprimir texto, y para un mensaje fijo sin nada especial adentro funciona perfectamente bien. El problema aparece en dos situaciones concretas. Primero, echo no interpreta secuencias de escape como \t o \n por defecto en bash (necesitas la bandera -e para eso), pero otros shells sí las interpretan por defecto — en particular dash, que en muchas distribuciones Linux es el /bin/sh real. Un script que asume el comportamiento de echo en bash puede imprimir texto distinto si alguien lo corre con sh script.sh en vez de bash script.sh, retomando la diferencia que viste antes en esta misma lección.
Segundo, y más traicionero: echo puede confundir el valor de una variable con una de sus propias banderas, porque para cuando echo recibe el argumento, las comillas ya se quitaron y solo ve texto plano.
printf no tiene ninguno de los dos problemas: su comportamiento sigue el mismo estándar en todos los sistemas, y separa estrictamente el formato ('%s\n') de los datos que le pasas después, así que nunca confunde un valor con una opción.
Ejemplo trabajado
value="-n"
echo "$value"
Qué esperar:
Nada. Ni el texto -n, ni siquiera un salto de línea. Bash interpretó ese argumento como la bandera -n de echo (suprimir el salto de línea final), no como el texto que querías imprimir — aunque venía de una variable con comillas dobles, porque para cuando echo lo recibe, ya es simplemente el texto -n, sin ningún rastro de que alguna vez estuvo entre comillas. Ahora la misma variable con printf:
printf '%s\n' "$value"
Qué esperar:
-n
printf nunca interpreta el segundo argumento como una opción propia — el formato ('%s\n') va primero y separado, y todo lo que sigue se trata como dato, sin excepciones. Por eso, cuando vas a imprimir el valor de una variable (en vez de un texto fijo que tú mismo escribiste), printf '%s\n' "$variable" es la opción más segura.
Comentarios y un encabezado que se explica solo
Cualquier línea que empiece con # es un comentario — bash la ignora por completo al ejecutar, excepto la primerísima línea del archivo, donde #! es el shebang, no un comentario normal. Un buen hábito, que ya usaste en cada script de esta lección sin nombrarlo todavía, es abrir con un encabezado de dos o tres líneas que explique, sin que nadie tenga que preguntar: qué hace el script y cómo se invoca.
#!/usr/bin/env bash
#
# session-log.sh — registra quién se conectó, desde qué máquina y cuándo.
# Uso: ./session-log.sh <entorno>
# Ejemplo: ./session-log.sh production
Ese encabezado cuesta tres líneas escribirlo hoy y ahorra minutos a quien abra el archivo dentro de seis meses — incluido tú mismo.
Ejemplo trabajado
Junta todo lo que viste en esta lección en un solo script: shebang, encabezado, variables, sustitución de comandos, un parámetro posicional y read, cerrando con printf para la salida.
#!/usr/bin/env bash
#
# session-log.sh — registra quién se conectó, desde qué máquina y cuándo.
# Uso: ./session-log.sh <entorno>
# Ejemplo: ./session-log.sh production
environment="$1"
user_name="$(whoami)"
host_name="$(hostname)"
today="$(date +%F)"
read -r -p "Motivo de la conexión: " reason
printf 'Entorno: %s\n' "$environment"
printf 'Usuario: %s\n' "$user_name"
printf 'Máquina: %s\n' "$host_name"
printf 'Fecha: %s\n' "$today"
printf 'Motivo: %s\n' "$reason"
Guárdalo, dale permiso de ejecución y corre:
chmod +x session-log.sh
./session-log.sh production
Qué esperar (el script se pausa en read; aquí se muestra lo que tecleaste):
Motivo de la conexión: revisar logs de despliegue
Entorno: production
Usuario: alex
Máquina: alexs-macbook.local
Fecha: 2026-07-21
Motivo: revisar logs de despliegue
Cada pieza de esta lección aparece aquí cumpliendo su función: $1 trajo production desde la línea de comandos, los tres $( ) capturaron datos del sistema en el momento exacto en que el script corrió, read se detuvo a esperar un dato que solo el usuario podía dar, y printf imprimió todo con un formato predecible, sin sorpresas de banderas mal interpretadas.
Errores comunes
"Corrí mi script sin el argumento y no me marcó ningún error — solo el mensaje salió incompleto". Qué pasa: en bash, una variable o un parámetro posicional que nunca se definió no es un error por defecto — se convierte silenciosamente en una cadena vacía. Si corres ./session-log.sh sin ningún argumento, $1 no explota: simplemente vale "", y tu script sigue corriendo hasta el final con un campo Entorno: vacío en vez de detenerse a avisarte que faltó algo. Por qué ocurre: bash prioriza que los scripts sigan corriendo incluso con datos incompletos, a menos que tú actives explícitamente un modo más estricto. Cómo detectarlo: revisa la salida completa buscando campos vacíos donde esperabas un valor, no un mensaje de error. Cómo corregirlo por ahora: documenta claramente en el encabezado del script qué argumentos espera y en qué orden; la forma de validar eso automáticamente con if y detener el script con un código de salida propio es exactamente el tema de la próxima lección.
"Puse el texto entre comillas simples pensando que igual iba a mostrar el valor de mi variable". Qué pasa: echo 'Hola, $user_name' imprime literalmente Hola, $user_name, con el signo de dólar y el nombre de la variable tal cual, en vez de Hola, Alex. Por qué ocurre: las comillas simples no expanden absolutamente nada — ni variables, ni sustituciones de comando, ni nada que empiece con $. Son la opción correcta solo cuando quieres texto completamente literal, incluyendo cualquier $ que aparezca dentro. Cómo detectarlo: la salida muestra el símbolo $ y el nombre de la variable en vez de su valor. Cómo corregirlo: cambia a comillas dobles (echo "Hola, $user_name") cada vez que necesites que algo adentro se expanda.
"Le di permiso de ejecución con chmod +x, pero cuando alguien más lo corrió con sh mi_script.sh se comportó distinto". Qué pasa: chmod +x y el shebang solo tienen efecto cuando el script se invoca como ./mi_script.sh. Si alguien lo corre explícitamente con sh mi_script.sh, el shebang nunca se lee — y en varias distribuciones Linux (Debian, Ubuntu), sh no es un alias de bash: es dash, un shell más limitado que no soporta varias de las características que usaste en esta lección. Por qué ocurre: escribir sh archivo o bash archivo elige el intérprete explícitamente, sin pasar nunca por la línea #! de tu archivo. Cómo detectarlo: si el mismo script produce resultados distintos entre dos personas, pregunta con qué comando exacto lo invocaron, no solo si le dieron permiso de ejecución. Cómo corregirlo: invoca siempre con ./script.sh para que se respete el shebang que escribiste, o si necesitas ser explícito, usa bash script.sh — nunca sh script.sh para un script que usa características de bash.
Ejercicios
1. De comandos sueltos a script
Tienes esta secuencia, que ya corriste a mano dos veces esta semana:
df -h
uptime
Escribe un script llamado health-check.sh con shebang portable, un comentario de encabezado que explique qué hace, permiso de ejecución, y que al correrlo con ./health-check.sh imprima la salida de ambos comandos.
Ver solución
printf '%s\n' \
'#!/usr/bin/env bash' \
'# health-check.sh - muestra espacio en disco y tiempo de actividad de la máquina.' \
'' \
'df -h' \
'uptime' \
> health-check.sh
chmod +x health-check.sh
./health-check.sh
Por qué funciona: el shebang #!/usr/bin/env bash le dice al sistema qué intérprete usar buscándolo en el PATH; chmod +x le da al archivo el bit de ejecución que ./health-check.sh necesita para correrlo directamente; y una vez que el sistema entrega el archivo a bash, los comandos corren en el mismo orden en que los escribiste, exactamente como si los hubieras tecleado a mano.
2. Encuentra el bug de comillas
Este fragmento falla cuando $backup_name contiene un espacio:
backup_name="daily backup.tar.gz"
cp report.tar.gz $backup_name
¿Qué error concreto vas a ver, y cómo lo corriges?
Ver solución
cp va a fallar con algo como cp: target 'backup.tar.gz' is not a directory (o un error equivalente), porque sin comillas bash parte $backup_name en dos palabras — daily y backup.tar.gz — y se lo entrega a cp como si fueran dos argumentos separados en vez de uno solo. cp interpreta eso como "copia report.tar.gz y daily dentro de un directorio llamado backup.tar.gz", que no existe.
La corrección es agregar comillas dobles alrededor de la variable:
cp report.tar.gz "$backup_name"
Por qué funciona: las comillas dobles preservan el valor completo de la variable como una sola palabra, espacios incluidos, en vez de dejar que bash vuelva a partirlo usando el mismo criterio que usa para separar los argumentos que tecleas en la terminal.
3. Predice la salida
Tienes este script guardado como report.sh:
#!/usr/bin/env bash
echo "Script: $0"
echo "Args recibidos: $#"
echo "Segundo argumento: $2"
Si lo corres así: ./report.sh staging alex, ¿qué imprime cada línea?
Ver solución
Script: ./report.sh
Args recibidos: 2
Segundo argumento: alex
Por qué funciona: $0 siempre contiene el nombre con el que invocaste el script, tal cual lo escribiste (./report.sh); $# cuenta cuántos argumentos siguen después del nombre del script (dos: staging y alex); y $2 toma específicamente el segundo de esos argumentos en el orden en que los escribiste, ni el primero ni el total.
4. El valor que se disfraza de bandera
Este fragmento debería imprimir el valor de $flag, pero cuando flag vale -e, no imprime nada de lo esperado:
flag="-e"
echo "$flag"
¿Por qué pasa esto, y cómo lo arreglas para que siempre imprima el valor tal cual, sin importar qué texto tenga adentro?
Ver solución
echo "$flag" termina ejecutando, en la práctica, echo -e sin ningún texto detrás — bash entrega -e como argumento a echo, y echo lo interpreta como su propia bandera para activar la interpretación de secuencias de escape, no como el texto que querías mostrar. El resultado es que no ves -e impreso en pantalla, sino el comportamiento de la bandera (en este caso, sin texto extra, básicamente no imprime nada útil).
La corrección es usar printf en vez de echo:
printf '%s\n' "$flag"
Por qué funciona: printf separa estrictamente el formato ('%s\n') de los datos que le siguen; todo lo que llega después del formato se trata siempre como dato literal, nunca como una opción propia de printf, sin importar qué texto contenga.
Resumen y siguiente paso
Antes de avanzar deberías poder:
- escribir el shebang
#!/usr/bin/env bashy explicar por qué se prefiere sobre una ruta fija como#!/bin/bash; - distinguir cuándo corre un script con
./script.sh(necesitaxy respeta el shebang),bash script.sh(ignora el shebang) osh script.sh(puede ser un shell distinto, comodash); - declarar variables sin espacios alrededor del
=, y explicar por qué casi siempre las citas van con comillas dobles y no simples; - capturar la salida de un comando con
$( ), leer parámetros posicionales ($0,$1,$#,$@) y pedir un dato al usuario conread -r -p; - elegir
printfsobreechocuando imprimes el valor de una variable, en vez de un texto fijo que tú mismo escribiste.
Hoy tu script corre en línea recta: lee argumentos, captura datos, pide entrada, imprime resultados — pero nunca decide nada. No verifica si le diste el argumento que esperaba, no distingue entre un archivo que existe y uno que no, no reintenta ni se detiene con un código de error propio cuando algo sale mal. Eso es exactamente lo que resuelve la próxima lección: if, case, bucles for y while read, exit con códigos documentados, set -euo pipefail explicado bandera por bandera, y el criterio honesto de cuándo un script ya creció demasiado y toca reescribirlo en Python.
Recursos
- Shell Parameters — GNU Bash Reference Manual — referencia oficial de los parámetros posicionales y especiales (
$0,$1,$#,$@,$*). - Quoting — GNU Bash Reference Manual — la diferencia exacta entre comillas simples, dobles y sin comillas, directo de la fuente.
- Command Substitution — GNU Bash Reference Manual — cómo funciona
$( )y por qué se prefiere sobre las comillas invertidas. - Bash Builtin Commands — GNU Bash Reference Manual — documentación oficial de
read(incluidas las banderas-py-r) yprintf. - env(1) — Linux manual page — qué hace exactamente
enval buscar un programa en tuPATH, la base técnica del shebang#!/usr/bin/env bash. - printf(1) — Linux manual page — sintaxis completa de las secuencias de formato (
%s,%d, etc.) que aceptaprintf.