feat: verif-desktop — audit des fichiers .desktop
Nouveau script d'audit des fichiers .desktop : détecte les exécutables manquants, apps cachées, icônes introuvables et erreurs de syntaxe (via desktop-file-validate). Documentation man incluse. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Executable
+130
@@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Audit des fichiers .desktop : chemins manquants, apps cachées, erreurs de syntaxe
|
||||||
|
|
||||||
|
DIRS=(
|
||||||
|
"$HOME/.local/share/applications"
|
||||||
|
"/usr/share/applications"
|
||||||
|
)
|
||||||
|
|
||||||
|
RED='\033[0;31m'
|
||||||
|
YEL='\033[0;33m'
|
||||||
|
GRN='\033[0;32m'
|
||||||
|
BLU='\033[0;34m'
|
||||||
|
RST='\033[0m'
|
||||||
|
|
||||||
|
ok=0
|
||||||
|
warn=0
|
||||||
|
err=0
|
||||||
|
|
||||||
|
check_file() {
|
||||||
|
local f="$1"
|
||||||
|
local name
|
||||||
|
name=$(basename "$f")
|
||||||
|
local issues=()
|
||||||
|
local hints=()
|
||||||
|
|
||||||
|
# Ignorer les fichiers qui ne sont pas des Application affichables
|
||||||
|
local type
|
||||||
|
type=$(grep -m1 "^Type=" "$f" 2>/dev/null | cut -d= -f2-)
|
||||||
|
[[ "$type" != "Application" ]] && return
|
||||||
|
|
||||||
|
# Détecter si c'est un gestionnaire d'URL ou un fichier système (NoDisplay=true y est normal)
|
||||||
|
local is_url_handler=false
|
||||||
|
grep -q "^MimeType=.*x-scheme-handler" "$f" 2>/dev/null && is_url_handler=true
|
||||||
|
|
||||||
|
local is_user_dir=false
|
||||||
|
[[ "$f" == "$HOME/.local/share/applications/"* ]] && is_user_dir=true
|
||||||
|
|
||||||
|
# NoDisplay ou Hidden : signaler uniquement dans le dossier utilisateur et si pas gestionnaire d'URL
|
||||||
|
local nodisplay hidden
|
||||||
|
nodisplay=$(grep -m1 "^NoDisplay=" "$f" | cut -d= -f2-)
|
||||||
|
hidden=$(grep -m1 "^Hidden=" "$f" | cut -d= -f2-)
|
||||||
|
if [[ "$is_user_dir" == true && "$is_url_handler" == false ]]; then
|
||||||
|
[[ "$nodisplay" == "true" ]] && issues+=("caché (NoDisplay=true) — n'apparaît pas dans le menu")
|
||||||
|
[[ "$hidden" == "true" ]] && issues+=("caché (Hidden=true) — n'apparaît pas dans le menu")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Exec : extraire le premier token (sans %F %u etc.)
|
||||||
|
local exec_line exec_bin
|
||||||
|
exec_line=$(grep -m1 "^Exec=" "$f" | cut -d= -f2-)
|
||||||
|
# Retirer les guillemets englobants éventuels et les arguments %x
|
||||||
|
exec_bin=$(echo "$exec_line" | awk '{print $1}' | tr -d '"' | sed 's/%[a-zA-Z]$//')
|
||||||
|
|
||||||
|
if [[ -z "$exec_bin" ]]; then
|
||||||
|
issues+=("Exec manquant")
|
||||||
|
elif [[ "$exec_bin" == /* ]]; then
|
||||||
|
# Chemin absolu
|
||||||
|
if [[ ! -f "$exec_bin" ]]; then
|
||||||
|
issues+=("exécutable introuvable : $exec_bin")
|
||||||
|
elif [[ ! -x "$exec_bin" ]]; then
|
||||||
|
issues+=("exécutable non exécutable : $exec_bin")
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Commande dans le PATH (ignorer les wrappers shell)
|
||||||
|
if [[ "$exec_bin" != "sh" && "$exec_bin" != "bash" && "$exec_bin" != "env" ]]; then
|
||||||
|
if ! command -v "$exec_bin" &>/dev/null; then
|
||||||
|
issues+=("commande introuvable dans PATH : $exec_bin")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Icône (chemin absolu uniquement — les noms de thème sont difficiles à vérifier)
|
||||||
|
local icon
|
||||||
|
icon=$(grep -m1 "^Icon=" "$f" | cut -d= -f2-)
|
||||||
|
if [[ "$icon" == /* && ! -f "$icon" ]]; then
|
||||||
|
hints+=("icône introuvable : $icon")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Validation syntaxique (desktop-file-validate)
|
||||||
|
if command -v desktop-file-validate &>/dev/null; then
|
||||||
|
local syntax_out
|
||||||
|
syntax_out=$(desktop-file-validate "$f" 2>&1 | grep -v "^$")
|
||||||
|
while IFS= read -r line; do
|
||||||
|
[[ -z "$line" ]] && continue
|
||||||
|
if echo "$line" | grep -q "error:"; then
|
||||||
|
issues+=("syntaxe : ${line#*error: }")
|
||||||
|
elif echo "$line" | grep -q "warning:"; then
|
||||||
|
hints+=("syntaxe : ${line#*warning: }")
|
||||||
|
fi
|
||||||
|
done <<< "$syntax_out"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Affichage
|
||||||
|
local max_hints=3
|
||||||
|
if [[ ${#issues[@]} -gt 0 ]]; then
|
||||||
|
echo -e "${RED}✗ $name${RST}"
|
||||||
|
for i in "${issues[@]}"; do
|
||||||
|
echo -e " ${RED}→ $i${RST}"
|
||||||
|
done
|
||||||
|
local shown=0
|
||||||
|
for h in "${hints[@]}"; do
|
||||||
|
(( shown >= max_hints )) && { echo -e " ${YEL}~ … (${#hints[@]} avertissements au total)${RST}"; break; }
|
||||||
|
echo -e " ${YEL}~ $h${RST}"
|
||||||
|
(( shown++ ))
|
||||||
|
done
|
||||||
|
(( err++ ))
|
||||||
|
elif [[ ${#hints[@]} -gt 0 ]]; then
|
||||||
|
echo -e "${YEL}~ $name${RST}"
|
||||||
|
local shown=0
|
||||||
|
for h in "${hints[@]}"; do
|
||||||
|
(( shown >= max_hints )) && { echo -e " ${YEL}~ … (${#hints[@]} avertissements au total)${RST}"; break; }
|
||||||
|
echo -e " ${YEL}~ $h${RST}"
|
||||||
|
(( shown++ ))
|
||||||
|
done
|
||||||
|
(( warn++ ))
|
||||||
|
else
|
||||||
|
echo -e "${GRN}✓ $name${RST}"
|
||||||
|
(( ok++ ))
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for dir in "${DIRS[@]}"; do
|
||||||
|
[[ -d "$dir" ]] || continue
|
||||||
|
echo -e "\n${BLU}=== $dir ===${RST}"
|
||||||
|
while IFS= read -r -d '' f; do
|
||||||
|
check_file "$f"
|
||||||
|
done < <(find "$dir" -maxdepth 1 -name "*.desktop" -print0 | sort -z)
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo -e "Résultat : ${GRN}$ok OK${RST} ${YEL}$warn avertissements${RST} ${RED}$err erreurs${RST}"
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
tags:
|
||||||
|
- scripts
|
||||||
|
nom: verif-desktop
|
||||||
|
description: Audit des fichiers .desktop — chemins manquants, apps cachées, erreurs de syntaxe
|
||||||
|
---
|
||||||
|
|
||||||
|
# NOM
|
||||||
|
|
||||||
|
verif-desktop - Audit des fichiers .desktop de Linux Mint
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
verif-desktop
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
Vérifie l'ensemble des fichiers `.desktop` présents dans `~/.local/share/applications/` et `/usr/share/applications/`.
|
||||||
|
|
||||||
|
Pour chaque fichier, le script contrôle :
|
||||||
|
|
||||||
|
- **Exécutable manquant** : le chemin absolu dans `Exec=` n'existe pas sur le disque
|
||||||
|
- **Exécutable non exécutable** : le fichier existe mais n'a pas le bit `+x`
|
||||||
|
- **Commande introuvable** : la commande dans `Exec=` n'est pas dans le `$PATH`
|
||||||
|
- **App cachée** : `NoDisplay=true` ou `Hidden=true` dans le dossier utilisateur (l'app n'apparaît pas dans le menu)
|
||||||
|
- **Icône manquante** : `Icon=` pointe vers un chemin absolu inexistant
|
||||||
|
- **Erreurs de syntaxe** : signalées par `desktop-file-validate` (catégories invalides, clés dépréciées…)
|
||||||
|
|
||||||
|
Les gestionnaires d'URL (`MimeType=x-scheme-handler/...`) et les fichiers système sont traités différemment : `NoDisplay=true` y est attendu et n'est pas signalé comme erreur.
|
||||||
|
|
||||||
|
# COMPATIBILITÉ
|
||||||
|
|
||||||
|
Linux Mint (Cinnamon). Nécessite `desktop-file-utils` pour la validation syntaxique :
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install desktop-file-utils
|
||||||
|
```
|
||||||
|
|
||||||
|
# EXEMPLES
|
||||||
|
|
||||||
|
Lancer l'audit complet :
|
||||||
|
```
|
||||||
|
verif-desktop
|
||||||
|
```
|
||||||
|
|
||||||
|
# CODES DE RETOUR
|
||||||
|
|
||||||
|
- `✓` vert — fichier valide
|
||||||
|
- `~` jaune — avertissement non bloquant
|
||||||
|
- `✗` rouge — erreur : l'application ne fonctionnera pas ou n'apparaîtra pas dans le menu
|
||||||
|
|
||||||
|
# VERSIONS
|
||||||
|
|
||||||
|
-26.05.1
|
||||||
|
: Version originale
|
||||||
|
|
||||||
|
# AUTEURS
|
||||||
|
|
||||||
|
Cédric Abonnel - \<canl.sb2023@acemail.fr>
|
||||||
|
|
||||||
|
# RAPPORT D'ERREURS
|
||||||
|
|
||||||
|
Pour signaler des erreurs ou des problèmes :
|
||||||
|
https://git.abonnel.fr/cedricAbonnel/scripts-bash
|
||||||
Reference in New Issue
Block a user