D'après ce que je peux comprendre, les fichiers .desktop
sont des raccourcis permettant 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 sur le fichier qui lui est associé, par exemple. en double-cliquant sur firefox.desktop
exécute Firefox. Cependant, je ne trouve pas le moyen de faire la même chose via un terminal.
Si je fais gnome-open foo.desktop
, il ouvre simplement foo.desktop
sous forme de fichier texte. Si je le rends exécutable puis que je l'exécute en bash, il échoue simplement (ce qui est attendu, ce n'est clairement pas le script bash).
EDIT: Faire exec /fullpath/foo.desktop
me donne un message Permission denied
, même si je change de propriétaire pour moi-même. Si je m’exécute et que je fais la même commande, l’onglet du terminal que j’utilise est tout simplement fermé (je suppose qu’il se bloque). Enfin, si je fais Sudo exec /fullpath/foo.desktop
, je reçois une erreur en signalant Sudo: exec: command not found
.
Telle est ma question, comment puis-je exécuter un fichier foo.desktop
à partir du terminal?
La commande qui est exécutée est contenue dans le fichier du bureau, précédée de Exec=
afin que vous puissiez l'extraire et l'exécuter comme suit:
`grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &
Pour décomposer cela
grep '^Exec' filename.desktop - finds the line which starts with Exec
| tail -1 - only use the last line, in case there are multiple
| sed 's/^Exec=//' - removes the Exec from the start of the line
| sed 's/%.//' - removes any arguments - %u, %f etc
| sed 's/^"//g' | sed 's/" *$//g' - removes " around command (if present)
`...` - means run the result of the command run here
& - at the end means run it in the background
Vous pouvez mettre ceci dans un fichier, disons ~/bin/deskopen
avec le contenu
#!/bin/sh
`grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &
Puis le rendre exécutable
chmod +x ~/bin/deskopen
Et alors vous pourriez faire, par exemple
deskopen /usr/share/applications/ubuntu-about.desktop
Les arguments (%u
, %F
etc) sont détaillés dans http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#exec-variables - aucun des ils sont pertinents pour le lancement en ligne de commande.
Avec n'importe quel ubuntu récent qui supporte gtk-launch
, allez simplement
gtk-launch <file>
où est le nom du fichier .desktop sans la partie .desktop
Donc gtk-launch foo
ouvre foo.desktop
Le fichier .desktop doit se trouver dans/usr/share/applications,/usr/local/share/applications ou ~/.local/share/applications (- vous pouvez apparemment utiliser .desktop si vous le souhaitez.
Utilisable depuis le terminal ou alt + F2 (alt + F2 enregistre la commande dans l'historique si facilement accessible)
A partir d'aujourd'hui (12h10) le bogue est toujours présent. Cela dépend en fait du fonctionnement de gvfs-open
(appelé par xdg-open
).
Malgré tout, j’ai réussi à contourner rapidement le problème (en m'inspirant du code source de Nautilus). C'est un peu compliqué, mais fonctionne parfaitement sur Ubuntu 12.10, en ajoutant une icône significative (pas plus de ?
) sur le lanceur Unity.
Tout d'abord, j'ai écrit un script python à l'aide de Gio et l'ai placé sous le nom ~/bin/run-desktop
:
#!/usr/bin/python
from gi.repository import Gio
import sys
def main(myname, desktop, *uris):
launcher = Gio.DesktopAppInfo.new_from_filename(desktop)
launcher.launch_uris(uris, None)
if __== "__main__":
main(*sys.argv)
Le script doit avoir l'autorisation de l'exécutable, j'ai donc lancé ceci dans un terminal:
chmod +x ~/bin/run-desktop
Ensuite, j'ai créé l'entrée relative .desktop
sur ~/.local/share/applications/run-desktop.desktop
:
[Desktop Entry]
Version=1.0
Name=run-desktop
Exec=run-desktop %U
MimeType=application/x-desktop
Terminal=false
Type=Application
Enfin, j'ai associé l'entrée en tant que gestionnaire par défaut dans ~/.local/share/applications/mimeapps.list
sous la section [Default Applications]
comme suit:
[Default Applications]
....
application/x-desktop=run-desktop.desktop
À présent:
xdg-open
quelque chose.desktop fonctionne comme prévu#!/usr/bin/xdg-open
hashbang au-dessus d'une entrée de bureau exécutable fonctionne aussiCe sera un travail inutile lorsque gvfs-open
résoudra le bogue, mais entre-temps ...
Vous devriez vraiment utiliser gtk-launch
s'il est disponible. Cela fait généralement partie du paquet 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 l’installation du fichier . Desktop (c’est-à-dire situé dans /usr/share/applications
ou ~/.local/share/applications
).
Donc, pour contourner ce problème, nous pouvons utiliser une petite fonction haletante de Bash qui installe temporairement le fichier souhaité . Desktop avant de le lancer. Le "bon" moyen d'installer un fichier . Desktop est via desktop-file-install
mais je vais l'ignorer.
launch(){
# Usage: launch PATH [URI...]
# NOTE: The bulk of this function is executed in a subshell, i.e. `(..)`
# This isn't strictly necessary, but it keeps everything
# out of the global namespace and lessens the likelihood
# of side effects.
(
# where you want to install the launcher to
appdir=$HOME/.local/share/applications
# the template used to install the launcher
template=launcher-XXXXXX.desktop
# ensure $1 has a .desktop extension, exists, is a normal file, is readable, has nonzero size
# optionally use desktop-file-validate for stricter checking
# desktop-file-validate "$1" 2>/dev/null || {
[[ $1 = *.desktop && -f $1 && -r $1 && -s $1 ]] || {
echo "ERROR: you have not supplied valid .desktop file" >&2
return 1
}
# ensure the temporary launcher is deleted upon exit
trap 'rm "$launcherfile" &>/dev/null' EXIT
# create a temp file to overwrite later
launcherfile=$(mktemp -p "$appdir" "$template")
launchername=${launcherfile##*/}
# overwrite temp file with the launcher file
if cp "$1" "$launcherfile" &>/dev/null; then
gtk-launch "$launchername" "${@:2}"
else
echo "ERROR: failed to copy launcher to applications directory" >&2
return 1
fi
)
}
Vous pouvez l'utiliser comme ça (et également transmettre des arguments supplémentaires ou des URI si vous le souhaitez):
launch PATH [URI...]
launch ./path/to/shortcut.desktop
Si vous souhaitez analyser et exécuter manuellement un fichier . Desktop, vous pouvez le faire à l'aide de la commande awk
suivante:
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Si vous souhaitez traiter la commande awk
comme un script tout-en-un; nous pouvons même afficher un message d'erreur et quitter 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 "ERROR: Failed to identify Exec line\n" > "/dev/stderr"} else {printf "ERROR: Failed to identify Exec line in \047%s\047\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'
Les commandes susmentionnées vont:
%f
, %u
, %U
). Il est possible de remplacer ceux-ci par des arguments de position comme le prévoit la spécification, mais cela compliquerait considérablement le problème. Voir les dernières Spécification d'entrée sur le burea .Remarque: ce script AWK aborde quelques cas Edge qui peuvent ou ne peuvent pas être traités correctement par certaines des autres réponses. Plus précisément, cette commande supprime plusieurs variables Exec (en prenant soin de ne pas supprimer le symbole%), n'exécutera qu'une seule commande Exec line et se comportera comme prévu, même si la ligne Exec line contient un ou plusieurs signes d’égalité (par exemple, script.py --profile=name
).
Juste quelques autres avertissements ... Selon la spécification, TryExec est:
Chemin d'accès à un fichier exécutable sur le 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).
Dans cet esprit, il n’a aucun sens d’exécuter sa valeur.
Quelques autres préoccupations sont Path et Terminal. Path comprend le répertoire de travail dans lequel exécuter le programme. Terminal est un booléen indiquant si le programme est exécuté dans une fenêtre de terminal. Tous ces problèmes peuvent être résolus, mais il est inutile de réinventer la roue car il existe déjà des implémentations de la spécification. Si vous souhaitez implémenter Path, gardez à l'esprit que system()
génère un sous-processus, vous ne pouvez donc pas modifier le répertoire de travail en effectuant quelque chose comme system("cd \047" working_directory "\047"); system(command)
. Cependant, vous pourriez probablement faire quelque chose comme system("cd \047" working_directory "\047 && " command)
. Note\047 sont des guillemets simples (pour que la commande ne soit pas interrompue sur les chemins contenant des espaces).
Je vole une page de Carlo ici , qui a suggéré de créer un script Python pour utiliser le module gi. Voici un moyen minimal d'exécuter le même code à partir du shell sans avoir à créer un fichier et à vous préoccuper des entrées/sorties.
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
}
Puis exécutez la fonction lanceur comme suit:
launch ./path/to/shortcut.desktop
Notez que l'utilisation des URI est facultative. En outre, aucune vérification d'erreur n'est effectuée. Vous devez donc vous assurer que le programme de lancement existe et qu'il est lisible (avant de l'utiliser) si vous souhaitez que votre script soit durable.
Même si OP ne posait pas de questions sur KDE, vous pouvez utiliser la commande suivante pour tous ceux qui l'exécutent:
kioclient exec <path-to-desktop-file>
Sur Fedora, cela est inclus dans le __pm code kde-runtime
.
Vous pouvez utiliser dex .
dex foo.desktop
exo-open [[path-to-a-desktop-file]...]
semble fonctionner dans la version 13.10, si exo-utils est installé (comme c'est le cas avec Xubuntu).
Addendum à la réponse de Hamish.
Étant donné le script deskopen, vous pouvez utiliser une référence à celle-ci en tant que ligne Shebang dans un fichier . Desktop, car le caractère de commentaire est toujours #
. C'est-à-dire, mettez ceci comme première ligne du fichier . Desktop:
#!/usr/bin/env deskopen
Marquez ensuite le fichier . Desktop en tant que fichier exécutable (par exemple avec un chmod +x whatever.desktop
), puis vous pourrez
path/to/whatever.desktop
et voilà - L'application va s'ouvrir! (Complétez le fichier d'icône que j'ai spécifié, bien que je ne sache pas comment.)
Maintenant, si vous souhaitez é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 shift
ing, mais cela continuait à me donner une "mauvaise substitution" ...
Il n'y a actuellement aucune application qui réponde à vos besoins dans les archives Ubuntu. Quelques efforts sont en cours pour créer une solution générale offrant une intégration pour les environnements de bureau (tels que openbox) qui ne sont pas conformes à ces spécifications XDG.
Arch Linux travaille sur une implémentation de xdg-autostart basée sur les bibliothèques python-xdg. D'après ce que je peux trouver, cela ne semble pas encore tout à fait complet, mais il existe des rapports de succès.
Il existe également une implémentation C++ de xdg-autostart sur gitorious (http://gitorious.org/fr/xdg-autostart/) qui bénéficierait probablement d'une utilisation plus large.
Si l'une de ces solutions vous convient, envisagez de soumettre le travail nécessaire à l'inclusion dans Debian ou Ubuntu.
Pour utiliser l’un ou l’autre des outils avec openstart, vous devez l’appeler dans /etc/xdg/openbox/autostart.sh (si je lis correctement la documentation openbox). Si cela ne fonctionne pas, vous pouvez probablement l'appeler dans n'importe lequel des scripts d'initialisation de session openbox.
Je n'ai pas de solution immédiate répondant à l'exigence de "à l'aide d'une commande standard", mais si vous souhaitez analyser de manière minimale les fichiers .desktop
ou si vous souhaitez créer un alias Bash, les opérations suivantes devraient fonctionner :
awk -F= '/Exec=/{system($2); exit}' foo.desktop
une autre approche, qui pourrait être intéressante, consisterait à créer une méthode binfmt-misc
au niveau du noyau, qui correspond aux fichiers .desktop
(voir grep -r . /proc/sys/fs/binfmt_misc/
pour les modèles que vous avez activés).
À la fin de la journée, quelque chose devra analyser quelque part les fichiers .desktop
, il s’agit simplement de savoir comment "standard/par défaut".
J'ai pris le script de Carloréponse ci-dessus et j'ai tenté de l'améliorer pour mon propre usage sur le bureau.
Cette version du script vous permettra d'exécuter n'importe quelle application comme si vous l'aviez entrée sur le HUD, à condition que ce soit probablement le premier résultat. Il vous permet également de passer des arguments de fichier pour les fichiers .desktop qui ne prennent pas en charge les URI.
#!/usr/bin/env python
from gi.repository import Gio
from argparse import ArgumentParser
import sys, os
def find_app(search_string):
for group in Gio.DesktopAppInfo.search(search_string):
for entry in group:
try:
return Gio.DesktopAppInfo.new(entry)
except: pass
return None
def main(args):
launcher = None
if os.path.isfile(args.appName):
try:
# If it's a file, do that first.
launcher = Gio.DesktopAppInfo.new_from_filename(args.appName)
except TypeError:
print "'" + args.appName + "' is not a .desktop file"
sys.exit(-1)
# If it's a .desktop file in the DB, try using that
if launcher is None and args.appName.endswith('.desktop'):
try:
launcher = Gio.DesktopAppInfo.new(args.appName)
except TypeError: pass
if launcher is None:
# Search for the app by the text given
launcher = find_app(args.appName)
if launcher is None:
print "No app named " + args.appName + " could be found"
sys.exit(-1)
if (launcher.supports_uris()):
launcher.launch_uris(args.uris, None)
Elif (launcher.supports_files()):
launcher.launch(list({ Gio.File.parse_name(x) for x in args.uris }), None)
else :
launcher.launch()
if __== "__main__":
argParser = ArgumentParser(description="Launch a .desktop file or application")
argParser.add_argument("appName",
help="the name of any application, a desktop file's basename, or a concrete path to a desktop file",
action='store'
)
argParser.add_argument("uris",
nargs='*',
help="Files or URIs to pass to the application"
)
args = argParser.parse_args()
main(args)
(Compilé à partir des différentes autres réponses ici)
En fonction de votre système et des divers bogues qui peuvent ou non exister sur votre système, essayez les étapes suivantes jusqu'à ce que l'un d'entre eux fonctionne:
xdg-open program_name.desktop
exo-open program_name.desktop
gtk-launch program_name.desktop
kioclient exec program_name.desktop
dex program_name.desktop
Notez que sur les systèmes Ubuntu, vos lanceurs de bureau "Menu Démarrer" sont disponibles dans /usr/share/applications/
.
À titre d'exemple, pour montrer quelles commandes ci-dessus fonctionnent ou non sur mon système Ubuntu 14.04, voici les résultats des appels suivants pour moi:
xdg-open /usr/share/applications/Eclipse_for_cpp.desktop
# Echoue à cause d'un bogue (essaie de me faire sauvegarder ce fichier .desktop)exo-open /usr/share/applications/Eclipse_for_cpp.desktop
# Worksgtk-launch /usr/share/applications/Eclipse_for_cpp.desktop
# échoue avec "gtk-launch: aucune application de ce type"kioclient exec /usr/share/applications/Eclipse_for_cpp.desktop
# Worksdex /usr/share/applications/Eclipse_for_cpp.desktop
# échoue, & Sudo apt install dex
ne peut pas localiser le paquet dexEn essayant de tester ces fichiers, j'ai trouvé le moyen le plus simple de vérifier que le DM ou le gestionnaire de session ferait ce que je pensais être d'ouvrir le répertoire environnant dans un navigateur de dossier d'interface utilisateur, puis de double-cliquer dessus pour l'ouvrir. .
Si vous êtes en ligne de commande: gvfs-open .
ou gnome-open .
l'ouvrira dans le navigateur de dossiers configuré.
Le système sed ne reflétera pas le comportement du sous-ministre, y compris des choses délicates telles que des évasions et citant les endroits où vous ne voudriez vraiment pas avoir un comportement alternatif. Ce n'est pas une ligne de commande, mais cela a validé les choses. J'ai également trouvé utile de configurer Terminal=true
pour le débogage.
Ceci SO réponse est ce qui m’a clairement expliqué: n’essayez pas d’exécuter le fichier de bureau, mais exécutez le fichier indiqué dans le fichier de bureau.
Par exemple, exécutez /home/jsmith/Desktop/x11vnc.sh
Exec=/home/jsmith/Desktop/x11vnc.sh
Assurez-vous que le script sur lequel pointe votre fichier de bureau est également exécutable.
Si ça ne marche toujours pas. Rendre le fichier de bureau exécutable dans le terminal en changeant Terminal=true
et le placer dans un script bash. Exécutez le script pour intercepter la sortie d'erreur. Revenir en arrière lorsque les erreurs sont corrigées.
La réponse de Hamish est excellente, mais j'aimerais suggérer une alternative plus simple, avec moins de tuyauterie:
$(awk -F= '/^Exec/||/^TryExec/ {print $2;exit}' /usr/share/applications/firefox.desktop)
Dans ce cas, awk
recherche une ligne commençant par Exec
, puis nous imprimons simplement les champs après cette ligne. En utilisant for et =
, nous imprimons le champ 2, c’est-à-dire tout ce qui suit ce champ. Les accolades aux extrémités des commandes, $(...)
, sont des substitutions de paramètres. Shell exécutera donc toutes les commandes awk renvoyées; dans ce cas, il retourne la commande réelle qui vient après Exec=
.
Dans de rares cas, il peut y avoir plus d'un signe =
, ce qui est toujours une possibilité. Pour cela, je suggère
$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)