From c2cd1e4240e74907c28f3bedb7c2b8afeb2c0d49 Mon Sep 17 00:00:00 2001 From: Ricardo Monla Date: Sun, 7 Jun 2026 00:08:37 -0300 Subject: [PATCH] =?UTF-8?q?v2.9.0:=20men=C3=BA=20de=20cat=C3=A1logo=20en?= =?UTF-8?q?=20dos=20niveles=20=E2=80=94=20categor=C3=ADa=20=E2=86=92=20ISO?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit download_from_catalog() refactorizada en 4 funciones: _catalog_load() — parsea isos.conf agrupando por sección # ── _catalog_menu_categorias() — muestra las categorías con conteo de ISOs _catalog_menu_isos(cat) — muestra solo las ISOs de la categoría elegida _catalog_do_download() — ejecuta la descarga (sin cambios funcionales) El usuario elige primero la categoría (rm-ISOs, Debian, Ubuntu, etc.) y luego ve solo las ISOs de esa categoría, evitando la lista larga. Co-Authored-By: Claude Sonnet 4.6 --- rm-multiboot.sh | 218 +++++++++++++++++++++++++++++------------------- 1 file changed, 133 insertions(+), 85 deletions(-) diff --git a/rm-multiboot.sh b/rm-multiboot.sh index 241513b..9a75c20 100755 --- a/rm-multiboot.sh +++ b/rm-multiboot.sh @@ -5,7 +5,7 @@ # Autor: Lic. Ricardo MONLA # Email: rmonla@gmail.com # GitHub: https://github.com/ricardomonla/rm-MULTIBOOT -# Versión: 2.8.0 +# Versión: 2.9.0 # Licencia: MIT # # Uso: sudo ./rm-multiboot.sh @@ -19,7 +19,7 @@ set -euo pipefail # ─── Constantes ─────────────────────────────────────────────────────────────── -readonly SCRIPT_VERSION="2.8.0" +readonly SCRIPT_VERSION="2.9.0" readonly SCRIPT_AUTHOR="Lic. Ricardo MONLA" readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly ISOS_CONF="$SCRIPT_DIR/isos.conf" @@ -985,107 +985,130 @@ fetch_catalog() { wget -q --timeout=8 -O "$tmp" "$ISOS_CONF_URL" 2>/dev/null fi - # Si el archivo descargado tiene contenido válido, lo usamos if [[ -s "$tmp" ]] && grep -q '|' "$tmp" 2>/dev/null; then - echo "$tmp" - return 0 + echo "$tmp"; return 0 fi rm -f "$tmp" - - # Fallback: archivo local junto al script - if [[ -f "$ISOS_CONF" ]]; then - echo "$ISOS_CONF" - return 0 - fi - + [[ -f "$ISOS_CONF" ]] && { echo "$ISOS_CONF"; return 0; } return 1 } -download_from_catalog() { +# Parsea el catálogo agrupado por categorías. +# Popula los arrays globales: _CAT_NAMES _CAT_URLS _CAT_CATS _CAT_LABELS +_catalog_load() { + local catalog_file="$1" + _CAT_NAMES=(); _CAT_URLS=(); _CAT_CATS=(); _CAT_LABELS=() + local current_cat="Sin categoría" + + while IFS= read -r line; do + # Detectar línea de categoría: "# ── Nombre ────" + if [[ "$line" == *'# ──'* ]]; then + local cat_name + cat_name=$(echo "$line" | sed 's/.*# ── //' | sed 's/[[:space:]]*─*[[:space:]]*$//') + [[ -n "$cat_name" ]] && current_cat="$cat_name" + local found=false + local l; for l in "${_CAT_LABELS[@]:-}"; do + [[ "$l" == "$current_cat" ]] && { found=true; break; } + done + [[ "$found" == false ]] && _CAT_LABELS+=("$current_cat") + continue + fi + [[ "$line" =~ ^[[:space:]]*# ]] && continue + [[ -z "${line// }" ]] && continue + + local name url + IFS='|' read -r name url <<< "$line" + name="${name#"${name%%[! ]*}"}"; name="${name%"${name##*[! ]}"}" + url="${url#"${url%%[! ]*}"}"; url="${url%"${url##*[! ]}"}" + [[ -z "$url" ]] && continue + + _CAT_NAMES+=("$name") + _CAT_URLS+=("$url") + _CAT_CATS+=("$current_cat") + done < "$catalog_file" +} + +# Muestra el menú de categorías y navega a la elegida. +_catalog_menu_categorias() { banner - step "Descargar ISO desde el catálogo" + step "Descargar ISO — Elegí una categoría" echo "" - # Obtener catálogo - local catalog_src catalog_file origin_label - printf " Cargando catálogo desde GitHub..." - if catalog_file=$(fetch_catalog); then - if [[ "$catalog_file" == "$ISOS_CONF" ]]; then - origin_label="${Y}(sin red — usando archivo local)${N}" - else - origin_label="${G}(GitHub — actualizado)${N}" - fi - printf "\r ${G}✓${N} Catálogo cargado %b\n\n" "$origin_label" - else - printf "\r ${R}✗${N} No se pudo obtener el catálogo.\n" - echo -e " Verificá la conexión a internet o colocá ${W}isos.conf${N} junto al script.\n" - pause; banner; detect_system; menu_principal; return - fi - - # Leer entradas válidas del catálogo (ignorar comentarios y líneas vacías) - local -a names urls - while IFS='|' read -r name url; do - [[ "$name" =~ ^[[:space:]]*# ]] && continue - [[ -z "${name// }" ]] && continue - name="${name#"${name%%[! ]*}"}"; name="${name%"${name##*[! ]}"}" - url="${url#"${url%%[! ]*}"}"; url="${url%"${url##*[! ]}"}" - [[ -z "$url" ]] && continue - names+=("$name") - urls+=("$url") - done < "$catalog_file" - - # Limpiar archivo temporal si vino de GitHub - [[ "$catalog_file" != "$ISOS_CONF" ]] && rm -f "$catalog_file" - - if [[ "${#names[@]}" -eq 0 ]]; then - err "El catálogo está vacío o no tiene entradas válidas." - pause; banner; detect_system; menu_principal; return - fi - - # Mostrar catálogo - echo -e " ${W}Catálogo disponible:${N}\n" local i=1 - for name in "${names[@]}"; do - local iso_filename - iso_filename=$(basename "${urls[$((i-1))]%%\?*}") - local estado="" - [[ -f "$ISO_DIR/$iso_filename" ]] && estado=" ${G}[ya descargada]${N}" - printf " ${C}%2d)${N} %-42s%b\n" "$i" "$name" "$estado" - i=$((i+1)) + for cat in "${_CAT_LABELS[@]}"; do + local n=0 + local c; for c in "${_CAT_CATS[@]}"; do [[ "$c" == "$cat" ]] && n=$(( n + 1 )); done + local s=""; [[ $n -gt 1 ]] && s="s" + printf " ${C}%d)${N} %-42s ${W}%d ISO%s${N}\n" "$i" "$cat" "$n" "$s" + i=$(( i + 1 )) done - echo " 0) Volver" + echo " 0) Volver al menú principal" + echo "" + + local opt + opt=$(ask "¿Qué categoría? [0-${#_CAT_LABELS[@]}]") + [[ "$opt" == "0" ]] && { banner; detect_system; menu_principal; return; } + + if ! [[ "$opt" =~ ^[0-9]+$ ]] || \ + [[ "$opt" -lt 1 ]] || [[ "$opt" -gt "${#_CAT_LABELS[@]}" ]]; then + err "Opción inválida."; pause; _catalog_menu_categorias; return + fi + + _catalog_menu_isos "${_CAT_LABELS[$((opt-1))]}" +} + +# Muestra las ISOs de una categoría y permite seleccionar una para descargar. +_catalog_menu_isos() { + local cat="$1" + banner + step "Descargar ISO — $cat" + echo "" + + local -a names urls + local idx; for idx in "${!_CAT_NAMES[@]}"; do + [[ "${_CAT_CATS[$idx]}" == "$cat" ]] || continue + names+=("${_CAT_NAMES[$idx]}") + urls+=("${_CAT_URLS[$idx]}") + done + + local j=1 + for name in "${names[@]}"; do + local iso_filename estado="" + iso_filename=$(basename "${urls[$((j-1))]%%\?*}") + [[ -f "$ISO_DIR/$iso_filename" ]] && estado=" ${G}[ya descargada]${N}" + printf " ${C}%2d)${N} %-42s%b\n" "$j" "$name" "$estado" + j=$(( j + 1 )) + done + echo " 0) ← Categorías" echo "" local opt opt=$(ask "¿Cuál descargamos? [0-${#names[@]}]") - - if [[ "$opt" == "0" ]]; then - banner; detect_system; menu_principal; return - fi + [[ "$opt" == "0" ]] && { _catalog_menu_categorias; return; } if ! [[ "$opt" =~ ^[0-9]+$ ]] || \ [[ "$opt" -lt 1 ]] || [[ "$opt" -gt "${#names[@]}" ]]; then - err "Opción inválida."; pause; download_from_catalog; return + err "Opción inválida."; pause; _catalog_menu_isos "$cat"; return fi - local idx=$((opt - 1)) - local chosen_name="${names[$idx]}" - local chosen_url="${urls[$idx]}" + _catalog_do_download "${names[$((opt-1))]}" "${urls[$((opt-1))]}" "$cat" +} + +# Ejecuta la descarga de una ISO seleccionada del catálogo. +_catalog_do_download() { + local chosen_name="$1" chosen_url="$2" chosen_cat="$3" local iso_filename gdrive_id="" - # ── Resolver filename y origen de descarga ──────────────────────────────── if is_gdrive_url "$chosen_url"; then gdrive_id=$(gdrive_file_id "$chosen_url") if [[ -z "$gdrive_id" ]]; then err "No se pudo extraer el File ID de la URL de Google Drive." - pause; banner; detect_system; menu_principal; return + pause; _catalog_menu_categorias; return fi - # Intentar obtener el nombre real del archivo desde headers printf " Obteniendo nombre del archivo desde Google Drive..." iso_filename=$(gdrive_real_filename "$gdrive_id") if [[ -z "$iso_filename" ]]; then - # Fallback: generar nombre desde el nombre del catálogo iso_filename=$(echo "$chosen_name" | tr '[:upper:]' '[:lower:]' \ | tr ' ' '-' | sed 's/[^a-z0-9._-]//g').iso fi @@ -1098,20 +1121,18 @@ download_from_catalog() { echo "" echo -e " ${W}ISO seleccionada:${N}" - ok "Nombre: ${W}$chosen_name${N}" - ok "Archivo: $iso_filename" - if [[ -n "$gdrive_id" ]]; then - ok "Origen: ${C}Google Drive${N} (ID: $gdrive_id)" - else - ok "URL: ${C}$chosen_url${N}" - fi + ok "Categoría: ${W}$chosen_cat${N}" + ok "Nombre: ${W}$chosen_name${N}" + ok "Archivo: $iso_filename" + [[ -n "$gdrive_id" ]] \ + && ok "Origen: ${C}Google Drive${N} (ID: $gdrive_id)" \ + || ok "URL: ${C}$chosen_url${N}" echo "" - # Verificar si ya existe if [[ -f "$dest" ]]; then warn "Esta ISO ya está descargada en la partición MULTIBOOT." if ! confirm "¿Descargar de nuevo y sobreescribir?"; then - banner; detect_system; menu_principal; return + _catalog_menu_categorias; return fi fi @@ -1120,10 +1141,9 @@ download_from_catalog() { echo -e " Espacio libre en MULTIBOOT: $(( avail_k / 1024 / 1024 )) GB\n" if ! confirm "¿Iniciar descarga?"; then - banner; detect_system; menu_principal; return + _catalog_menu_categorias; return fi - # ── Descargar ───────────────────────────────────────────────────────────── echo "" step "Descargando $iso_filename..." echo "" @@ -1141,11 +1161,9 @@ download_from_catalog() { ok "Descarga completada: $iso_filename" - # Generar entrada GRUB step "Generando entrada de arranque..." local distro distro=$(detect_distro "$iso_filename") - # Preferir el nombre del catálogo si es más descriptivo [[ "$distro" == "Linux" ]] && distro="$chosen_name" generate_grub_entry "$iso_filename" "$distro" @@ -1158,6 +1176,36 @@ download_from_catalog() { pause; banner; detect_system; menu_principal } +# Punto de entrada: carga el catálogo y muestra el menú de categorías. +download_from_catalog() { + banner + step "Descargar ISO desde el catálogo" + echo "" + + local catalog_file origin_label + printf " Cargando catálogo desde GitHub..." + if catalog_file=$(fetch_catalog); then + [[ "$catalog_file" == "$ISOS_CONF" ]] \ + && origin_label="${Y}(sin red — usando archivo local)${N}" \ + || origin_label="${G}(GitHub — actualizado)${N}" + printf "\r ${G}✓${N} Catálogo cargado %b\n\n" "$origin_label" + else + printf "\r ${R}✗${N} No se pudo obtener el catálogo.\n" + echo -e " Verificá la conexión a internet o colocá ${W}isos.conf${N} junto al script.\n" + pause; banner; detect_system; menu_principal; return + fi + + _catalog_load "$catalog_file" + [[ "$catalog_file" != "$ISOS_CONF" ]] && rm -f "$catalog_file" + + if [[ "${#_CAT_NAMES[@]}" -eq 0 ]]; then + err "El catálogo está vacío o no tiene entradas válidas." + pause; banner; detect_system; menu_principal; return + fi + + _catalog_menu_categorias +} + # ============================================================================= # AGREGAR ISO DESDE RUTA LOCAL