Skip to content

Instantly share code, notes, and snippets.

@bonnebulle
Last active November 26, 2024 22:47
Show Gist options
  • Save bonnebulle/0ed8f0b5e3022a486d5586007e4a859b to your computer and use it in GitHub Desktop.
Save bonnebulle/0ed8f0b5e3022a486d5586007e4a859b to your computer and use it in GitHub Desktop.
#!/bin/bash
# GIST
# https://gist.github.com/bonnebulle/0ed8f0b5e3022a486d5586007e4a859b
# OBJECTIF
# Remove unused/dead menu entries in xfce/linux menu
# VARS
editor_modifications="codium"
install_commande_auto="yay -Syu --noconfirm --needed --overwrite \*"
install_commande_normal="yay -Syu --needed --overwrite \*"
install_commande_search="yay -Ss"
######################
# TODO more paths
# /usr/share/applications/
# ~/.local/share/applications/
# PARAMETERS
# --v : Vérifier .desktop
# --vd : Vérifier .desktop (mode détaillé)
# --r : Si dead - Supprimer / install ( normal )
# --ra : Si dead - Supprimer / install ( auto )
# PROMPT options
# r : remove
# g : keep/garder
# x : ignore
# i : install
# a : alt install
# s : search (yay)
# p : prompt (yay direct name install)
# e : edit
##################
## SOURCES
# https://stackoverflow.com/a/677212
# https://stackoverflow.com/a/20268787
# + CLAUDE IA + Cursor
# https://claude.site/artifacts/71f24c0d-67e4-477e-bd54-86a37c800884
# Fonction pour nettoyer et extraire la commande principale
clean_exec_command() {
local exec_line="$1"
# Supprimer "Exec=" s'il est présent
exec_line=$(echo "$exec_line" | sed -e 's/^Exec=//' | sed -e 's/^TryExec=//')
# Supprimer les options %U, %F, etc.
exec_line=$(echo "$exec_line" | sed -E 's/\s*%(f|F|u|U|d|D|n|N|i|c|k|v|m)//gi')
# Prendre le premier mot (la commande)
local first_cmd=$(echo "$exec_line" | awk '{print $1}')
# Résoudre les liens symboliques et les chemins absolus
if [[ "$first_cmd" == /* ]]; then
echo "$first_cmd"
else
echo "$first_cmd" 2>/dev/null
fi
}
# Fonction pour nettoyer et extraire la commande name
clean_exec_name() {
local exec_name="$1"
# Supprimer "Exec=" s'il est présent
exec_name=$(echo "$exec_name" | sed -e 's/^Name=//')
# Supprimer les options %U, %F, etc.
# exec_line=$(echo "$exec_line" | sed -E 's/\s*%(f|F|u|U|d|D|n|N|i|c|k|v|m)//gi')
# Prendre le premier mot (la commande)
local first_name=$(echo "$exec_name" | awk '{print $1}')
# TODO, Redo check
# Résoudre les liens symboliques et les chemins absolus
# if [[ "$first_cmd" == /* ]]; then
# echo "$first_cmd"
# else
# echo "$first_cmd" 2>/dev/null
# fi
echo $first_name
}
# Fonction pour tester si la commande est exécutable
test_exec_command() {
local cmd="$1"
# Vérifier si la commande existe dans le système
if command -v "$cmd" > /dev/null 2>&1; then
return 0
fi
# SOURCE :: https://stackoverflow.com/a/677212
if ! command -v $first_cmd 2>&1 >/dev/null
then
echo
echo
echo "----- $1 found"
return 0
else
echo
echo
echo "----- $1 ( not found )"
return 1
fi
}
# Fonction pour extraire le chemin d'exécution d'un fichier .desktop
extract_exec_path() {
grep -Ph '(?<=Exec=).*?( |$)' "$1" | head -n 1
}
extract_exec_name() {
# TODO explicit ^Name=... dont catch OptName=...
grep -Ph '(?<=Name=).*?( |$)' "$1" | head -n 1
}
# Fonction de suppression interactive
remove_desktop_file() {
local file="$1"
local exec_path="$2"
local sata="$3"
# SOURCE :: https://stackoverflow.com/a/20268787
if sudo grep -q '^IGNORE_MENU' "$file"; then
echo IGNORE_MENU présent dans
echo "--- $file"
echo "--- $exec_path"
else
# echo "debug $sata"
# Vérifier si le mode détaillé est demandé
if [[ $sata == "auto" ]]; then
auto_install=true
fi
# echo "debug install $sata :"
if [ "$auto_install" = true ]; then
install_commande_option=$install_commande_auto
else
install_commande_option=$install_commande_normal
fi
# echo "debug $install_commande_option"
# sleep 11000
# Vérifier si gio ou gvfs-trash est disponible
if command -v gio &> /dev/null; then
trash_cmd="gio trash"
elif command -v gvfs-trash &> /dev/null; then
trash_cmd="gvfs-trash"
else
echo "Erreur : Aucun outil de corbeille trouvé (gio ou gvfs-trash)"
return 1
fi
first_cmd_new=$(echo "$exec_path" | awk '{print $1}')
first_cmd_fix=$(echo "$first_cmd_new" | sed -e 's/^Exec=//' | sed -e 's/^TryExec=//')
lastpath=${first_cmd_fix##*/}
# echo "lastpath == "$lastpath
# echo "clean_name == "$clean_name
# Prompt de confirmation avec informations détaillées
read -p "Fichier .desktop --- '$file' ( commande : $exec_path )`echo $'\n\n> '`==> (a) $clean_name `echo $'\n> '`==> (i) $lastpath `echo $'\n\n> '`... manquant, déplacer vers la corbeille ? `echo $'\n> '`-- (r)emove / (g)arder / (x)ignorer`echo $'\n>'` -- (i)nstall / (a)lt / (n)ormal`echo $'\n>'` -- (p)rompt / (s)earch / (e)dit ? " response
# Convertir la réponse en minuscules
response=$(echo "$response" | tr '[:upper:]' '[:lower:]')
if [[ "$response" == "r" || "$response" == "remove" ]]; then
# Utiliser sudo si nécessaire (fichiers système)
# TODO add ~/.local/share/applications/*.desktop ??
if [[ "$file" == "/usr/share/applications/"* ]]; then
# Demander le mot de passe sudo
echo
echo "--- REMOVE"
echo "Ce fichier nécessite des permissions administratives."
if sudo -v; then
# Utiliser sudo pour déplacer le fichier
if sudo $trash_cmd "$file"; then
echo "Fichier '$file' déplacé dans la corbeille (avec permissions administratives)."
else
echo "Erreur lors du déplacement du fichier '$file' vers la corbeille."
return 1
fi
else
echo "Authentification sudo échouée. Opération annulée."
return 1
fi
else
# Fichiers utilisateur : pas besoin de sudo
if $trash_cmd "$file"; then
echo "Fichier '$file' déplacé dans la corbeille."
else
echo "Erreur lors du déplacement du fichier '$file' vers la corbeille."
return 1
fi
fi
echo
echo
elif [[ "$response" == "i" || "$response" == "install" ]]; then
echo
echo "----- install"
mycmd=$lastpath
echo
echo "install ( mod $sata ) :"
echo $mycmd
echo
echo
sleep 2
if [[ $($install_commande_search "$mycmd") ]]
then
$install_commande_option $mycmd
else
echo "--- INSTALLER DONT FOUND"
echo
remove_desktop_file "$1" "$2" "$3"
fi
elif [[ "$response" == "a" || "$response" == "alt" ]]; then
echo
echo "----- alt"
mycmd=$clean_name
echo
echo "install (alt)"
echo $mycmd
echo
sleep 2
if [[ $($install_commande_search "$mycmd") ]]
then
$install_commande_option "$mycmd"
else
echo "--- INSTALLER DONT FOUND -- Re_DO "
echo
remove_desktop_file "$1" "$2" "$3"
fi
elif [[ "$response" == "n" || "$response" == "normal" ]]; then
echo
echo "----- normal"
mycmd=$clean_name
echo
echo "install (normal -- skip auto)"
echo $mycmd
echo
sleep 2
if [[ $($install_commande_search "$mycmd") ]]
then
$install_commande_normal "$mycmd"
else
echo "--- INSTALLER DONT FOUND -- Re_DO "
echo
remove_desktop_file "$1" "$2" "$3"
fi
elif [[ "$response" == "e" || "$response" == "edit" ]]; then
echo
echo "EDIT $file"
$editor_modifications $file 2>&1 >/dev/null
echo
echo "--- BACK "
remove_desktop_file "$1" "$2" "$3"
elif [[ "$response" == "s" || "$response" == "search" ]]; then
read -p "-- search nom (prompt_name / n/s ) ? " sresponse
# sresponse=$(echo "sresponse" | tr '[:upper:]' '[:lower:]')
if [[ "$sresponse" != "n" && "$sresponse" != "no" && "$sresponse" != "s" ]]; then
echo
echo "----- search -- $sresponse"
echo
sleep 2
echo "--- RESULTAT ---"
# $mycmd
$install_commande_search $sresponse
echo
echo "----------------"
fi
echo "--- INSTALLER DONT FOUND -- Re_DO "
echo
remove_desktop_file "$1" "$2" "$3"
elif [[ "$response" == "x" || "$response" == "ignore" ]]; then
echo
echo "----- ignore -> ajoute IGNORE_MENU"
echo "----- BYPASS NEXT TIME"
# mycmd="$response"
if sudo grep -q '^IGNORE_MENU' "$file"; then
sudo sed -i 's/^IGNORE_MENU.*/IGNORE_MENU=ok/' "$file"
else
echo 'IGNORE_MENU=ok' | sudo tee -a "$file" > /dev/null
fi
elif [[ "$response" == "p" || "$response" == "prompt" ]]; then
read -p "-- install autre nom (prompt_name / n/x ) ? " presponse
presponse=$(echo "$presponse" | tr '[:upper:]' '[:lower:]')
echo
echo "----- prompt"
mycmd="$presponse"
if [[ $($install_commande_search "$mycmd") ]]
then
$install_commande_normal "$mycmd"
else
echo "--- RIEN TROUVÉ"
echo "--- INSTALLER DONT FOUND -- Re_DO "
echo
remove_desktop_file "$1" "$2" "$3"
fi
else
echo "Suppression annulée pour '$file'."
fi
fi # IGNORE_MENU
}
# Fonction de vérification des exécutables
verify_desktop_files() {
local count=0
local missing_count=0
local detailed_output=false
# Vérifier si le mode détaillé est demandé
if [[ "$1" == "--d" ]]; then
detailed_output=true
fi
# Boucle de vérification des applications
for i in /usr/share/applications/*.desktop ~/.local/share/applications/*.desktop; do
# Vérifier si le fichier existe réellement
if [ -f "$i" ]; then
# Extraire le chemin d'exécution
exec_path=$(extract_exec_path "$i")
# Extraire le nom du fichier sans le chemin
filename=$(basename "$i")
# Nettoyer et extraire la commande
clean_cmd=$(clean_exec_command "$exec_path")
# Tester la commande
if ! test_exec_command "$clean_cmd"; then
echo -e "Fichier : $filename"
echo "Ligne Exec originale : $exec_path"
echo "Commande extraite : $clean_cmd"
# Incrémenter le compteur de commandes manquantes
((missing_count++))
# Mode détaillé : afficher plus d'informations
if [ "$detailed_output" = true ]; then
echo "Détails supplémentaires :"
which "$clean_cmd" 2>&1 || echo "Aucune correspondance trouvée"
fi
fi
# Incrémenter le compteur total
((count++))
fi
done
# Afficher le résultat final
echo -e "\nVérification terminée."
echo "Total des fichiers vérifiés : $count"
echo "Nombre de commandes manquantes : $missing_count"
}
forloop_r() {
# echo "debug forloop_r ==="
# echo "debug #1 $1"
for i in /usr/share/applications/*.desktop ~/.local/share/applications/*.desktop; do
if [ -f "$i" ]; then
# Extraire le chemin d'exécution
exec_path=$(extract_exec_path "$i")
# Extraire le nom du fichier sans le chemin
filename=$(basename "$i")
# Nettoyer et extraire la commande
clean_cmd=$(clean_exec_command "$exec_path")
# Nettoyer et extraire le nom
clean_name=$(extract_exec_name "$i" | sed -e 's/^Name=//' | tr '[:upper:]' '[:lower:]')
# Tester la commande
if ! test_exec_command "$clean_cmd"; then
remove_desktop_file "$i" "$exec_path" "$1"
fi
fi
done
}
# Fonction principale
main() {
case "$1" in
"--r")
# Mode suppression
# echo "debug r"
forloop_r "normal"
;;
"--ra")
# Mode suppression
# echo "debug ra"
forloop_r "auto"
;;
"--v")
# Mode vérification standard
verify_desktop_files
;;
"--vd")
# Mode vérification détaillé
verify_desktop_files --d
;;
*)
echo "Utilisation :"
echo
echo "--r : Si commande manquante`echo $'\n '` Supprimer / install ( norm )`echo $'\n '`"
echo "--ra : Si commande manquante`echo $'\n '` Supprimer / install ( auto )`echo $'\n '`"
echo "--v : Vérifier .desktop`echo $'\n '`"
echo "--vd : Vérifier .desktop (mode détaillé)"
echo
# Prompt de confirmation avec informations détaillées
read -p "r / ra / v / vd ? " responsea
# Convertir la réponse en minuscules
responsea=$(echo "$responsea" | tr '[:upper:]' '[:lower:]')
if [[ "$responsea" == "r" || "$responsea" == "ra" || "$responsea" == "rv" || "$responsea" == "vd" ]]; then
echo "GO --- " $responsea
echo "( wait )"
main "--$responsea"
else
echo "--wrong, exit"
exit 1
fi
;;
esac
}
# Appeler la fonction principale avec les arguments
main "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment