Icon Theme Manager: Gestor Avanzado de Cachés de Iconos con YAD y Autenticación Única
Una herramienta técnica en Bash para gestionar, detectar y actualizar temas de iconos de forma eficiente en distribuciones Linux basadas en Debian y otras.
Introducción Técnica
Uno de los problemas más comunes al instalar o modificar temas de iconos en Linux es la necesidad de actualizar manualmente los cachés con gtk-update-icon-cache. Esto se vuelve especialmente tedioso cuando se tienen temas tanto en /usr/share/icons como en ~/.local/share/icons, ya que requiere permisos de root en el primer caso.
Además, herramientas como Zenity presentan limitaciones importantes en el manejo de progreso y ejecución con privilegios. Por esta razón, desarrollé Icon Theme Manager, una solución completa que utiliza YAD (Yet Another Dialog) con estilos CSS modernos y un sistema inteligente de ejecución con una sola petición de contraseña.
Características Técnicas Principales
- Reemplazo completo de Zenity por YAD con estilos CSS personalizados (tema oscuro moderno).
- Autenticación única con pkexec: se solicita la contraseña solo una vez aunque se actualicen decenas de temas.
- Detección inteligente de temas válidos mediante la presencia de
index.theme. - Escaneo dual: temas del sistema (
/usr/share/icons) y del usuario (~/.local/share/icons). - Detección automática de distribución, entorno de escritorio y esquema de colores.
- Barra de progreso en tiempo real con información detallada.
- Interfaz moderna con CSS inline y mejor experiencia de usuario.
- Gestión segura de scripts temporales para ejecución privilegiada.
Aspectos Técnicos Destacados
1. Sistema de Autenticación Única
El mayor avance técnico de esta versión es el uso de un helper script temporal generado dinámicamente:
#!/bin/bash
THEMES=("$@")
for i in "${!THEMES[@]}"; do
THEME="${THEMES[$i]}"
NAME=$(basename "$THEME")
PROGRESS=$(( (i + 1) * 100 / TOTAL ))
echo "# Actualizando ($((i+1))/$TOTAL): $NAME"
echo "$PROGRESS"
gtk-update-icon-cache -f -t "$THEME" &>/dev/null
done
2. Interfaz Moderna con YAD + CSS
Se implementó un estilo oscuro moderno directamente en la variable YAD_CSS, mejorando significativamente la experiencia visual respecto a Zenity.
3. Detección Inteligente
El script detecta automáticamente:
- Distribución mediante
/etc/os-release - Entorno de escritorio (
$XDG_CURRENT_DESKTOP) - Tema actual de iconos mediante
gsettings - Temas válidos filtrando solo carpetas que contienen
index.theme
Instalación
La instalación es muy sencilla:
sudo nano /usr/local/bin/icon-theme-manager
# Pegar el script completo
#!/usr/bin/env bash
# ================================================
# Icon Theme Manager - Interfaz Moderna & 1 Pwd
# Usa YAD con CSS + Helper Script para pkexec único
# ================================================
APP_NAME="Icon Theme Manager"
APP_VERSION="3.0"
LOG_FILE="/tmp/icon-theme-manager.log"
# ================================================
# Configuración de Estilos CSS (Modern Dark Theme)
# ================================================
YAD_CSS="window { background-color: #1e1e1e; color: #e2e8f0; border-radius: 12px; border: 1px solid #3e3e3e; }
entry { background-color: #2d2d2d; border-radius: 6px; border: 1px solid #4a5568; }
text { background-color: transparent; color: #e2e8f0; }
button { background-color: #3b82f6; color: white; border-radius: 6px; border: none; padding: 8px 16px; font-weight: bold; box-shadow: 0 2px 4px rgba(0,0,0,0.3); transition: background 0.2s; }
button:hover { background-color: #60a5fa; }
list { border: 1px solid #3e3e3e; }
progress { text-shadow: none; color: #e2e8f0; font-weight: bold; }
* { font-family: 'Segoe UI', 'Roboto', 'Helvetica', sans-serif; font-size: 11pt; }"
# ================================================
# Funciones de Mensajería (YAD)
# ================================================
show_msg() {
local type="$1"
local text="$2"
case "$type" in
"info") yad --info --title="$APP_NAME" --text="$text" --width=500 --height=200 --css="$YAD_CSS" --button=gtk-ok:0 2>/dev/null ;;
"error") yad --error --title="$APP_NAME" --text="$text" --width=500 --height=200 --css="$YAD_CSS" --button=gtk-close:0 2>/dev/null ;;
"question") yad --question --title="$APP_NAME" --text="$text" --width=500 --height=180 --css="$YAD_CSS" --button=gtk-yes:0 --button=gtk-no:1 ;;
esac
}
# ================================================
# Dependencias
# ================================================
check_dependencies() {
local missing=()
command -v yad >/dev/null || missing+=("yad")
command -v gtk-update-icon-cache >/dev/null || missing+=("gtk-update-icon-cache")
if [[ ${#missing[@]} -gt 0 ]]; then
if show_msg "question" "Faltan dependencias: ${missing[*]}\n\n¿Instalarlas ahora?"; then
if command -v apt-get >/dev/null; then
pkexec apt-get update && pkexec apt-get install -y yad libgtk-3-bin
elif command -v dnf >/dev/null; then
pkexec dnf install -y yad gtk3
fi
else
exit 1
fi
fi
}
# ================================================
# Lógica de Escaneo de Iconos
# ================================================
scan_icon_themes() {
local themes=()
# Escanear sistema
if [[ -d "/usr/share/icons" ]]; then
for dir in /usr/share/icons/*/; do
[[ -f "${dir}index.theme" ]] && themes+=("/usr/share/icons/$(basename "${dir%/}")")
done
fi
# Escanear usuario
if [[ -d "$HOME/.local/share/icons" ]]; then
for dir in "$HOME/.local/share/icons/"*/; do
[[ -f "${dir}index.theme" ]] && themes+=("$HOME/.local/share/icons/$(basename "${dir%/}")")
done
fi
printf '%s\n' "${themes[@]}"
}
# ================================================
# ACTUALIZACIÓN CON UNA SOLA CONTRASEÑA
# ================================================
update_all_caches() {
local themes=()
mapfile -t themes < <(scan_icon_themes)
local total=${#themes[@]}
if [[ $total -eq 0 ]]; then
show_msg "error" "No se encontraron temas de iconos válidos (sin index.theme)."
return
fi
if ! show_msg "question" "Se actualizarán $total temas.\n\nSe requiere contraseña de administrador UNA sola vez.\n\n¿Continuar?"; then
return
fi
# Crear archivo de script auxiliar para ejecutar como root una sola vez
local helper_script="/tmp/icon-theme-helper-$$"
local pipe_output="/tmp/icon-theme-pipe-$$"
rm -f "$helper_script" "$pipe_output"
mkfifo "$pipe_output" # Crear pipe para el progreso en tiempo real
# Generar el script auxiliar con los temas como argumentos
cat > "$helper_script" </dev/null 2>&1; then
echo "[ERROR] Fallo en \$NAME" >&2
fi
done
echo "# ¡Actualización Completada!"
echo "100"
sleep 1 # Mantener el pipe abierto un poco
EOF
chmod +x "$helper_script"
# Ejecutar el helper script con pkexec (una sola vez) y enviar output al pipe
# Esto pedirá la contraseña UNA vez y luego actualizará todos los temas
pkexec "$helper_script" "${themes[@]}" > "$pipe_output" &
local pk_pid=$!
# Leer el pipe y mostrar progreso en YAD
cat "$pipe_output" | yad --progress \
--title="Actualizando Iconos..." \
--text="Iniciando proceso de actualización..." \
--width=550 --height=180 \
--percentage=0 \
--auto-close \
--css="$YAD_CSS" \
--button=gtk-cancel:1 &
local yad_pid=$!
# Limpiar cuando YAD se cierre
while kill -0 $yad_pid 2>/dev/null; do
sleep 0.5
# Si el proceso pkexec muere, cerrar YAD
if ! kill -0 $pk_pid 2>/dev/null; then
kill $yad_pid 2>/dev/null
fi
done
# Limpieza
wait $pk_pid 2>/dev/null
rm -f "$helper_script" "$pipe_output"
show_msg "info" "Se actualizaron $total temas de iconos correctamente."
}
# ================================================
# Menú Principal
# ================================================
main_menu() {
local choice
choice=$(yad --list --title="$APP_NAME" \
--text="Selecciona una acción:" \
--column="Acción" --column="Descripción" \
--width=700 --height=500 --center \
--no-headers --hide-column=1 \
--css="$YAD_CSS" \
"update_all" "🔄 Actualizar TODOS los Cachés (1 contraseña)" \
"list" "🎨 Listar Temas Instalados" \
"detect" "🖥️ Detectar Info del Sistema" \
"open_sys" "📁 Abrir /usr/share/icons" \
"open_usr" "📁 Abrir ~/.local/share/icons" \
"about" "ℹ️ Acerca de" \
--button="Ejecutar:0" --button="Salir:1" 2>/dev/null | awk -F'|' '{print $1}')
case "$choice" in
"update_all") update_all_caches ;;
"list")
yad --list --title="Temas Detectados" \
--column="Ubicación" --column="Nombre del Tema" --column="Ruta Absoluta" \
--width=900 --height=550 --css="$YAD_CSS" \
$(scan_icon_themes | sed 's|/usr/share/icons|SYSTEM|;s|'$HOME'/\.local/share/icons|USER|' | awk '{print $1, substr($2, index($2,"/")+1), $2}') \
--button=Cerrar:0
;;
"detect")
local distro=$(grep PRETTY_NAME /etc/os-release | cut -d= -f2 | tr -d '"')
local theme="N/A"
[[ -n "$XDG_CURRENT_DESKTOP" ]] && theme=$(gsettings get org.gnome.desktop.interface icon-theme 2>/dev/null | tr -d "'")
show_msg "info" "Distribución: $distro\n\nTemas de Iconos Actuales: $theme"
;;
"open_sys") xdg-open /usr/share/icons 2>/dev/null ;;
"open_usr") mkdir -p "$HOME/.local/share/icons" && xdg-open "$HOME/.local/share/icons" 2>/dev/null ;;
"about") show_msg "info" "$APP_NAME v$APP_VERSION\n\nDiseño modernizado con CSS YAD.\nActualización de iconos con una sola petición de contraseña." ;;
"exit"|"") exit 0 ;;
esac
main_menu
}
# ================================================
# Inicio
# ================================================
main() {
check_dependencies
main_menu
}
main "$@"
sudo chmod +x /usr/local/bin/icon-theme-manager
Uso
Una vez instalado, puedes ejecutarlo desde terminal con:
icon-theme-manager
O desde el menú de aplicaciones. La opción más útil es "Actualizar TODOS los Cachés", que actualizará todos los temas detectados con una sola autenticación.
Mejoras respecto a versiones anteriores
| Aspecto | Versión anterior (Zenity) | Versión 3.0 (YAD) |
|---|---|---|
| Estabilidad de progreso | Limitada | Excelente |
| Solicitudes de contraseña | Múltiples | Única |
| Apariencia | Básica | Moderna con CSS |
| Detección de temas | Simple | Inteligente (index.theme) |
Publicado por: [FedericoRaika] | Categoría: Linux • Bash Scripting • Herramientas

💬 Comentarios ()