201 votes

Exécution d'un fichier desktop dans le terminal

D'après ce que j'ai pu comprendre, les fichiers .desktop sont des raccourcis qui permettent de personnaliser les paramètres de l'application. Par exemple, j'en ai beaucoup dans mon dossier /usr/share/applications/.

Si j'ouvre ce dossier dans nautilus, je peux exécuter ces applications en double-cliquant simplement sur leur fichier associé, par exemple, double-cliquer sur firefox.desktop lance Firefox. Cependant, je ne trouve pas de moyen de faire la même chose via le terminal.

Si je fais gnome-open foo.desktop, cela ouvre simplement foo.desktop comme un fichier texte. Si je le rends exécutable puis le lance dans bash, cela échoue simplement (ce qui est attendu, ce n'est clairement pas un script bash).
EDIT : Faire exec /chemincomplet/foo.desktop me donne un message Permission denied, même si je change la propriété à moi-même. Si je le rends exécutable et que je fais la même commande, l'onglet terminal que j'utilise se ferme simplement (je suppose que cela plante). Enfin, si je fais sudo exec /chemincomplet/foo.desktop, j'obtiens une erreur signalant sudo : exec : command not found.

Voilà ma question, comment puis-je exécuter un fichier foo.desktop à partir du terminal?

37voto

Six Points 772

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 :

  1. Trouver la ligne commençant par Exec=
  2. Supprimer Exec=
  3. 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.
  4. Exécuter la commande
  5. 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.

34voto

couac Points 341

Vous pourriez utiliser dex.

Installer dex:

sudo apt install dex

Exécutez le fichier avec:

dex foo.desktop

20voto

Mnementh Points 19831
exo-ouvrir [[chemin-vers-un-fichier-de-bureau]...]

semble fonctionner dans la version 13.10, si exo-utils est installé (comme c'est le cas avec Xubuntu).

11voto

Gabriel Staples Points 5149

(Compilé à partir des différentes réponses ici)

En fonction de votre système, et des divers bogues qui peuvent exister ou non sur votre système, essayez les solutions suivantes jusqu'à ce que l'une d'elles fonctionne :

  1. xdg-open nom_du_programme.desktop
  2. exo-open nom_du_programme.desktop [mon choix préféré, chaque fois que cela fonctionne]
  3. gtk-launch nom_du_programme.desktop
  4. kioclient exec nom_du_programme.desktop
  5. dex nom_du_programme.desktop
  6. Ou, voici une commande de @Hamish Downer qui recherche le fichier *.desktop avec grep pour la ligne Exec= contenant la commande à exécuter, en enlevant les parties de cette ligne que nous ne voulons pas, puis l'exécute. C'est bien écrit et fonctionne bien pour la plupart des fichiers de bureau. Voir sa réponse pour une explication complète.

    # Pour exécuter la commande `Exec=` depuis filename.desktop en arrière-plan
    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' \
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') &
    
    # Ou, enlevez le `&` à la fin pour l'exécuter en premier plan afin que vous
    # puissiez voir la sortie de l'exécution de la commande aussi
    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' \
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g')

Notez que sur les systèmes Ubuntu, vos lanceurs de bureau du "menu de démarrage" sont disponibles dans /usr/share/applications/.

Par exemple, pour montrer lesquelles des commandes ci-dessus fonctionnent ou ne fonctionnent pas sur mon système Ubuntu 14.04, voici les résultats des appels suivants pour moi :

  1. xdg-open /usr/share/applications/eclipse_for_cpp.desktop # Échec en raison d'un bogue (essaie de me faire enregistrer ce fichier .desktop)
  2. exo-open /usr/share/applications/eclipse_for_cpp.desktop # Fonctionne
  3. gtk-launch /usr/share/applications/eclipse_for_cpp.desktop # Échec avec "gtk-launch: aucune application de ce type"
  4. kioclient exec /usr/share/applications/eclipse_for_cpp.desktop # Fonctionne
  5. dex /usr/share/applications/eclipse_for_cpp.desktop # Échec, & sudo apt install dex ne peut pas localiser le paquet dex
  6. $(grep '^Exec' /usr/share/applications/eclipse_for_cpp.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') & # Fonctionne

9voto

Paul Points 21

Addendum à la réponse de Hamish.

Étant donné le script deskopen, vous pouvez l'utiliser comme ligne shebang dans un fichier .desktop, étant donné que le caractère de commentaire est toujours #. Autrement dit, mettez ceci en première ligne du fichier .desktop :

#!/usr/bin/env deskopen

Ensuite, marquez le fichier .desktop comme exécutable (par exemple avec un chmod +x whatever.desktop), et ensuite vous pouvez

chemin/vers/whatever.desktop

et voilà -- L'application s'ouvrira ! (Avec le fichier d'icône que j'ai spécifié, bien que je n'aie aucune idée de comment.)

Maintenant, si vous voulez également que deskopen transmette des paramètres de ligne de commande, vous pouvez utiliser cette version légèrement modifiée :

#!/bin/sh
desktop_file=$1
shift
`grep '^Exec' "${desktop_file}" | sed 's/^Exec=//' | sed 's/%.//'` "$@" &

En passant, j'ai essayé d'utiliser "#{@:2}" au lieu de faire un shift, mais cela me renvoyait constamment une 'mauvaise substitution'...

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X