La bonne manière
Vous devriez vraiment utiliser gtk-launch
s'il est disponible. Il fait généralement partie du package libgtk-3-bin (cela peut varier en fonction de la distribution).
gtk-launch
est utilisé comme suit :
gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
Veuillez noter que gtk-launch
nécessite que le fichier .desktop soit installé (c'est-à-dire situé dans /usr/share/applications
ou ~/.local/share/applications
).
Alors, pour contourner cela, nous pouvons utiliser une petite fonction Bash "hackish" qui installe temporairement le fichier .desktop désiré avant de le lancer. La manière "correcte" d'installer un fichier .desktop est via desktop-file-install
mais je vais ignorer cela.
launch(){
# Usage: launch PATH [URI...]
# REMARQUE : La majorité de cette fonction est exécutée dans un sous-shell, c'est-à-dire `(..)`
# Ce n'est pas strictement nécessaire, mais cela garde tout
# en dehors de l'espace de nom global et réduit la probabilité
# d'effets secondaires.
(
# où vous voulez installer le lanceur
appdir=$HOME/.local/share/applications
# le modèle utilisé pour installer le lanceur
template=launcher-XXXXXX.desktop
# assurer que $1 a une extension .desktop, existe, est un fichier normal, est lisible, a une taille non nulle
# facultativement, utiliser desktop-file-validate pour un contrôle plus strict
# desktop-file-validate "$1" 2>/dev/null || {
[[ $1 = *.desktop && -f $1 && -r $1 && -s $1 ]] || {
echo "ERREUR : vous n'avez pas fourni un fichier .desktop valide" >&2
return 1
}
# s'assurer que le lanceur temporaire est supprimé à la sortie
trap 'rm "$launcherfile" &>/dev/null' EXIT
# créer un fichier temporaire à écraser ultérieurement
launcherfile=$(mktemp -p "$appdir" "$template")
launchername=${launcherfile##*/}
# écraser le fichier temporaire avec le fichier lanceur
if cp "$1" "$launcherfile" &>/dev/null; then
gtk-launch "$launchername" "${@:2}"
else
echo "ERREUR : échec de la copie du lanceur dans le répertoire des applications" >&2
return 1
fi
)
}
Vous pouvez l'utiliser comme ceci (et également transmettre des arguments ou des URI supplémentaires si vous le souhaitez) :
launch PATH [URI...]
launch ./chemin/vers/raccourci.desktop
L'alternative manuelle
Si vous voulez analyser et exécuter manuellement un fichier .desktop, vous pouvez le faire avec la commande awk
suivante :
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Si vous voulez traiter la commande awk
comme un script tout-en-un ; nous pouvons même afficher un message d'erreur et sortir avec un code de retour de 1 dans le cas où une commande Exec n'est pas trouvée :
awk 'BEGIN {command=""} /^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); command=$0; exit} END {if (command!="") {exit system(command)} else {if (FILENAME == "-") {printf "ERREUR : Impossible d'identifier la ligne Exec\n" > "/dev/stderr"} else {printf "ERREUR : Impossible d'identifier la ligne Exec dans \047%s\047\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'
Les commandes mentionnées feront :
- Trouver la ligne commençant par Exec=
- Supprimer Exec=
- Supprimer toutes les variables Exec (par exemple,
%f
, %u
, %U
). Il est possible de les remplacer par des arguments positionnels comme le spécifie la spécification, mais cela ajouterait une complexité significative au problème. Voir la dernière Spécification des entrées de bureau.
- Exécuter la commande
- Sortir immédiatement avec le code de sortie approprié (afin de ne pas exécuter plusieurs lignes Exec)
Remarquez que ce script AWK adresse quelques cas particuliers qui peuvent ou non être correctement traités par certaines des autres réponses. En particulier, cette commande supprime plusieurs variables Exec (en veillant à ne pas supprimer le symbole % autrement), exécutera uniquement une seule commande de ligne Exec, et se comportera comme prévu même si la commande de la ligne Exec contient un ou plusieurs signes égal (par exemple, script.py --profile=name
).
Juste quelques autres précautions... Selon la spécification, TryExec est :
Chemin vers un fichier exécutable sur disque utilisé pour déterminer si le programme est réellement installé. Si le chemin n'est pas un chemin absolu, le fichier est recherché dans la variable d'environnement $PATH. Si le fichier n'est pas présent ou s'il n'est pas exécutable, l'entrée peut être ignorée (ne pas être utilisée dans les menus, par exemple).
En gardant cela à l'esprit, cela n'a pas de sens d'exécuter sa valeur.
D'autres préoccupations sont Chemin et Terminal. Chemin consiste en le répertoire de travail dans lequel exécuter le programme. Terminal est un booléen qui indique si le programme est exécuté dans une fenêtre de terminal. Tout cela peut être abordé, mais il n'est pas nécessaire de réinventer la roue car il existe déjà des implémentations de la spécification. Si vous voulez implémenter Chemin, gardez à l'esprit que system()
spawn un sous-processus, donc vous ne pouvez pas changer le répertoire de travail en faisant quelque chose comme system("cd \047" répertoire_de_travail "\047"); system(command)
. Cependant, vous pourriez potentiellement faire quelque chose comme system("cd \047" répertoire_de_travail "\047 && " command)
. Notez que les \047 sont des guillemets simples (pour que la commande ne se casse pas sur des chemins avec des espaces).
L'alternative Python
Je m'inspire de Carlo ici, qui a suggéré de créer un script Python pour utiliser le module gi. Voici une manière minimale d'exécuter le même code depuis l'invite de commandes sans avoir à créer de fichier et se soucier de l'E/S.
launch(){
# Usage: launch PATH [URI...]
python - "$@" <<EOF
import sys
from gi.repository import Gio
Gio.DesktopAppInfo.new_from_filename(sys.argv[1]).launch_uris(sys.argv[2:])
EOF
}
Ensuite, exécutez la fonction de lancement comme suit :
launch ./chemin/vers/raccourci.desktop
Remarquez que l'utilisation d'URIs est facultative. De plus, aucune vérification d'erreur n'est effectuée, donc vous voudrez vous assurer que le lanceur existe et est lisible (avant de l'utiliser) si vous voulez que votre script soit robuste.