it-swarm.com.de

Ausführen einer .desktop-Datei im Terminal

Nach dem, was ich sammeln kann, sind .desktop -Dateien Verknüpfungen, mit denen die Einstellungen der Anwendung angepasst werden können. Zum Beispiel habe ich viele davon in meinem /usr/share/applications/ -Ordner.

Wenn ich diesen Ordner in nautilus öffne, kann ich diese Anwendungen ausführen, indem ich auf die zugehörige Datei doppelklicke, z. Durch Doppelklicken auf firefox.desktop wird Firefox ausgeführt. Ich kann jedoch keine Möglichkeit finden, dasselbe über das Terminal zu tun.

Wenn ich gnome-open foo.desktop mache, wird foo.desktop einfach als Textdatei geöffnet. Wenn ich es ausführbar mache und es dann in Bash ausführe, schlägt es einfach fehl (was erwartet wird, es ist eindeutig kein Bash-Skript).
BEARBEITEN: Wenn ich exec /fullpath/foo.desktop tue, erhalte ich eine Permission denied -Nachricht, auch wenn ich den Besitzer selbst wechsle. Wenn ich ausführbar mache und den gleichen Befehl ausführe, wird der von mir verwendete Terminal-Tab einfach geschlossen (ich vermute, er stürzt ab). Wenn ich schließlich Sudo exec /fullpath/foo.desktop mache, erhalte ich eine Fehlermeldung Sudo: exec: command not found.

Das ist meine Frage, wie kann ich eine foo.desktop -Datei vom Terminal ausführen?

140
Malabarba

Der ausgeführte Befehl ist in der Desktop-Datei enthalten, der Exec= vorangestellt ist, sodass Sie ihn wie folgt extrahieren und ausführen können:

`grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &

Um das aufzubrechen

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

Sie können dies in eine Datei einfügen, z. B. ~/bin/deskopen mit dem Inhalt

#!/bin/sh
`grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &

Dann mach es ausführbar

chmod +x ~/bin/deskopen

Und dann könntest du z

deskopen /usr/share/applications/ubuntu-about.desktop

Die Argumente (%u, %F usw.) finden Sie unter http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#exec) -variables - Keine von ihnen ist für den Start in der Befehlszeile relevant.

54
Hamish Downer

Die Antwort sollte sein

xdg-open program_name.desktop

Aber aufgrund von ein Fehler funktioniert dies nicht mehr.

83

Mit jedem aktuellen Ubuntu, das gtk-launch unterstützt, einfach loslegen

gtk-launch <file> wobei der Name der .desktop-Datei ohne den Teil .desktop ist

Also öffnet gtk-launch foofoo.desktop

( gtk-launch documentation )

Die .desktop-Datei sollte sich in/usr/share/applications,/usr/local/share/applications oder ~/.local/share/applications befinden.

Kann vom Terminal aus oder mit Alt + F2 verwendet werden (Alt + F2 speichert den Befehl in der Historie und ist so leicht zugänglich)

73
doug

Ab heute (12.10) ist der Bug immer noch vorhanden. Dies hängt davon ab, wie gvfs-open (aufgerufen von xdg-open) funktioniert.

Trotzdem schaffte ich eine schnelle Umgehung (Inspiration aus dem Nautilus-Quellcode stehlen). Es ist etwas kompliziert, funktioniert aber unter Ubuntu 12.10 einwandfrei und fügt dem Unity-Launcher ein aussagekräftiges Symbol (nicht mehr ?) hinzu.

Zuerst habe ich ein python Skript mit Gio geschrieben und es als ~/bin/run-desktop gespeichert:

#!/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)

Das Skript muss über die ausführbare Berechtigung verfügen, daher habe ich dies in einem Terminal ausgeführt:

chmod +x ~/bin/run-desktop

Dann habe ich den relativen Eintrag .desktop für ~/.local/share/applications/run-desktop.desktop erstellt:

[Desktop Entry]
Version=1.0
Name=run-desktop
Exec=run-desktop %U
MimeType=application/x-desktop
Terminal=false
Type=Application

Schließlich habe ich den Eintrag als Standard-Handler in ~/.local/share/applications/mimeapps.list im Abschnitt [Default Applications] wie folgt zugeordnet:

[Default Applications]
....
application/x-desktop=run-desktop.desktop

Jetzt:

  • xdg-open something.desktop funktioniert wie erwartet
  • #!/usr/bin/xdg-open Hashbang über einem ausführbaren Desktop-Eintrag funktioniert auch

Es wird nutzlose Arbeit sein, wenn gvfs-open den Fehler behebt, aber in der Zwischenzeit ...

38

Der richtige Weg

Sie sollten wirklich gtk-launch verwenden, wenn es verfügbar ist. Es ist normalerweise Teil des Pakets libgtk-3-bin (dies kann je nach Distribution variieren).

gtk-launch wird wie folgt verwendet:

gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name

Beachten Sie, dass für gtk-launch die . Desktop -Datei installiert sein muss (d. H. In /usr/share/applications oder ~/.local/share/applications).

Um dies zu umgehen, können wir eine kleine, hackige Bash-Funktion verwenden, die vorübergehend die gewünschte .desktop -Datei installiert, bevor sie gestartet wird. Die "richtige" Art, eine . Desktop -Datei zu installieren, ist über desktop-file-install, aber ich werde das ignorieren.

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

    )

}

Sie können es wie folgt verwenden (und auch zusätzliche Argumente oder URIs weitergeben, wenn Sie möchten):

launch PATH [URI...]
launch ./path/to/shortcut.desktop

Die manuelle Alternative

Wenn Sie eine . Desktop -Datei manuell analysieren und ausführen möchten, können Sie dies mit dem folgenden Befehl awk tun:

awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop

Wenn Sie den Befehl awk wie ein All-in-One-Skript behandeln möchten; Wir können sogar eine Fehlermeldung anzeigen und mit dem Rückkehrcode 1 beenden, falls ein Exec -Befehl nicht gefunden wird:

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}}'

Die oben genannten Befehle werden:

  1. Finde die Zeile beginnend mit Exec =
  2. Entfernen Sie Exec =
  3. Entfernen Sie alle Exec-Variablen (z. B. %f, %u, %U). Es ist möglich, diese durch Positionsargumente zu ersetzen, wie es die Spezifikation vorsieht, dies würde dem Problem jedoch eine erhebliche Komplexität hinzufügen. Siehe neueste Desktop Entry Specification .
  4. Führen Sie den Befehl aus
  5. Beenden Sie sofort mit dem entsprechenden Beendigungscode (um nicht mehrere Exec Zeilen auszuführen)

Beachten Sie, dass dieses AWK-Skript einige Edge-Fälle anspricht, die von einigen der anderen Antworten möglicherweise nicht ordnungsgemäß behandelt werden. Insbesondere werden mit diesem Befehl mehrere Exec -Variablen entfernt (wobei darauf geachtet wird, das% -Symbol nicht zu entfernen). Es wird nur ein einzelnes Exec ausgeführt. Zeilenbefehl und verhält sich erwartungsgemäß, auch wenn der Zeilenbefehl Exec ein oder mehrere Gleichheitszeichen enthält (z. B. script.py --profile=name).

Nur ein paar andere Vorbehalte ... Laut Spezifikation ist TryExec :

Pfad zu einer ausführbaren Datei auf der Festplatte, anhand derer festgestellt wird, ob das Programm tatsächlich installiert ist. Wenn der Pfad kein absoluter Pfad ist, wird die Datei in der Umgebungsvariablen $ PATH nachgeschlagen. Wenn die Datei nicht vorhanden oder nicht ausführbar ist, wird der Eintrag möglicherweise ignoriert (z. B. nicht in Menüs verwendet).

In diesem Sinne macht es keinen Sinn, seinen Wert auszuführen.

Einige andere Probleme sind Pfad und Terminal . Pfad besteht aus dem Arbeitsverzeichnis, in dem das Programm ausgeführt wird. Terminal ist ein Boolescher Wert, der angibt, ob das Programm in einem Terminal ausgeführt wird Fenster. Diese können alle angesprochen werden, aber es macht keinen Sinn, das Rad neu zu erfinden, da es bereits Implementierungen der Spezifikation gibt. Wenn Sie Path implementieren möchten, beachten Sie, dass system() einen Unterprozess erzeugt, sodass Sie das Arbeitsverzeichnis nicht ändern können, indem Sie etwas wie system("cd \047" working_directory "\047"); system(command) ausführen. . Vermutlich könnten Sie jedoch etwas wie system("cd \047" working_directory "\047 && " command) tun. Hinweis\047 sind einfache Anführungszeichen (damit der Befehl bei Pfaden mit Leerzeichen nicht unterbrochen wird).

Die Python Alternative

Ich habe eine Seite von Carlo hier gestohlen, der vorgeschlagen hat, ein Python -Skript zu erstellen, um das gi -Modul zu verwenden. Hier ist eine minimale Möglichkeit, denselben Code über die Shell auszuführen, ohne eine Datei erstellen und sich um die E/A kümmern zu müssen.

launch(){

# Usage: launch PATH [URI...]

python - "[email protected]" <<EOF
import sys
from gi.repository import Gio
Gio.DesktopAppInfo.new_from_filename(sys.argv[1]).launch_uris(sys.argv[2:])
EOF

}

Führen Sie dann die Launcher-Funktion wie folgt aus:

launch ./path/to/shortcut.desktop

Beachten Sie, dass die Verwendung von URIs optional ist. Außerdem wird keine Fehlerprüfung durchgeführt. Sie sollten daher sicherstellen, dass der Launcher vorhanden und lesbar ist (bevor Sie ihn verwenden), wenn Ihr Skript dauerhaft sein soll.

31
Six

Während OP nicht nach KDE fragte, kann für jeden, der KDE ausführt, der folgende Befehl verwendet werden:

kioclient exec <path-to-desktop-file>

Auf Fedora ist dies in der Drehzahl von kde-runtime enthalten.

26
Raman

Sie könnten dex verwenden.

dex foo.desktop
13
couac
exo-open [[path-to-a-desktop-file]...]

scheint in Version 13.10 zu funktionieren, wenn Exo-Utils installiert sind (wie es bei Xubuntu der Fall ist).

13
jarno

Nachtrag zu Hamishs Antwort.

Wenn Sie das deskopen-Skript verwenden, können Sie einen Verweis darauf als Shebang-Zeile in einer .desktop -Datei verwenden, da das Kommentarzeichen immer noch # ist. Das heißt, setzen Sie dies als erste Zeile der . Desktop -Datei:

#!/usr/bin/env deskopen

Dann markieren Sie die Datei .desktop als ausführbar (z. B. mit einem chmod +x whatever.desktop), und dann können Sie

path/to/whatever.desktop

und voilà - Die App wird geöffnet! (Vervollständigen Sie die angegebene Symboldatei, obwohl ich keine Ahnung habe, wie.)

Wenn Sie nun auch möchten, dass deskopen Befehlszeilenparameter durchläuft, können Sie stattdessen diese leicht geänderte Version verwenden:

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

Nebenbei habe ich versucht, "#{@:2}" anstelle von shift zu verwenden, aber es hat mir immer wieder "schlechte Substitution" beschert ...

8
pabst

Derzeit gibt es keine Anwendung, die das tut, was Sie in den Ubuntu-Archiven beschrieben haben. Derzeit werden einige Anstrengungen unternommen, um eine allgemeine Lösung für die Integration von Desktop-Umgebungen (z. B. Openbox) zu entwickeln, die diesen XDG-Spezifikationen nicht entsprechen.

Arch Linux arbeitet an einer Implementierung von xdg-autostart basierend auf den Python-xdg-Bibliotheken. Soweit ich weiß, scheint dies noch nicht vollständig zu sein, doch es gibt einige Erfolgsberichte.

Es gibt auch eine C++ - Implementierung von xdg-autostart auf gitorious (http://gitorious.org/xdg-autostart/), die wahrscheinlich von einer umfassenderen Verwendung profitieren würde.

Wenn eine der beiden Lösungen für Sie funktioniert, überlegen Sie bitte, ob Sie die erforderlichen Arbeiten für die Aufnahme in Debian oder Ubuntu einreichen möchten.

Um eines der beiden Tools mit openstart zu verwenden, rufen Sie es in /etc/xdg/openbox/autostart.sh auf (wenn ich die openbox-Dokumentation richtig lese). Wenn dies nicht funktioniert, können Sie es wahrscheinlich in einem der Openbox-Sitzungsinitialisierungsskripten aufrufen.

6
Emmet Hikory

Ich habe keine sofortige Lösung, die die Anforderung für "Verwenden eines Standardbefehls" erfüllt, aber wenn Sie die .desktop -Dateien nur minimal analysieren oder einen Bash-Alias ​​erstellen möchten, dann Folgendes sollte funktionieren:

  • awk -F= '/Exec=/{system($2); exit}' foo.desktop

ein anderer Ansatz, der interessant sein könnte, wäre die Erstellung einer binfmt-misc -Methode auf Kernelebene, die nicht mit .desktop -Dateien übereinstimmt (für die derzeit aktivierten Muster siehe grep -r . /proc/sys/fs/binfmt_misc/).

Letztendlich muss irgendetwas irgendwo die .desktop -Dateien analysieren, es ist nur eine Frage, wie "standard/default" das ist.

6
sladen

Ich habe das Skript aus Carlo'sanswer oben genommen und versucht, es für meinen eigenen Desktop zu verbessern.

Mit dieser Version des Skripts können Sie jede App so ausführen, als ob Sie sie im HUD eingegeben hätten, sofern dies wahrscheinlich das erste Ergebnis ist. Sie können auch Dateiargumente für Desktopdateien übergeben, die keine URIs unterstützen.

#!/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)
2
Fordi

(Zusammengestellt aus den verschiedenen anderen Antworten hier)

Versuchen Sie je nach System und den verschiedenen auf Ihrem System möglicherweise vorhandenen oder nicht vorhandenen Fehlern Folgendes, bis einer der Fehler behoben ist:

  1. xdg-open program_name.desktop
  2. exo-open program_name.desktop
  3. gtk-launch program_name.desktop
  4. kioclient exec program_name.desktop
  5. dex program_name.desktop

Beachten Sie, dass auf Ubuntu-Systemen Ihre "Startmenü" -Desktopstarter in /usr/share/applications/ verfügbar sind.

Als Beispiel, um zu zeigen, welche der obigen Befehle auf meinem Ubuntu 14.04-System funktionieren oder nicht, sind hier die Ergebnisse der folgenden Aufrufe für mich:

  1. xdg-open /usr/share/applications/Eclipse_for_cpp.desktop # Fehlerhaft (versucht, diese .desktop-Datei zu speichern)
  2. exo-open /usr/share/applications/Eclipse_for_cpp.desktop # Works
  3. gtk-launch /usr/share/applications/Eclipse_for_cpp.desktop # Schlägt fehl mit "gtk-launch: keine solche Anwendung"
  4. kioclient exec /usr/share/applications/Eclipse_for_cpp.desktop # Works
  5. dex /usr/share/applications/Eclipse_for_cpp.desktop # Schlägt fehl, & Sudo apt install dex kann den Paket-Dex nicht finden
1
Gabriel Staples

Beim Versuch, diese Dateien zu testen, habe ich die einfachste Möglichkeit gefunden, um zu überprüfen, ob der DM oder der Sitzungsmanager das erwartete Ergebnis erzielt, indem er das umgebende Verzeichnis in einem Browser für Benutzeroberflächenordner öffnet und dann darauf doppelklickt .

Wenn Sie sich in einer Befehlszeile befinden: gvfs-open . oder gnome-open . öffnet sie im konfigurierten Ordner-Browser.

Das Sed-Ding wird das Verhalten des DM nicht widerspiegeln, einschließlich fummeliger Dinge wie Fluchten und Zitieren, wo man wirklich kein alternatives Verhalten haben möchte. Es ist keine Befehlszeile, aber es hat die Dinge validiert. Ich fand auch die Einstellung Terminal=true nützlich für das Debuggen.

1
Danny Staple

Dies SO answer machte es mir klar: Versuchen Sie nicht, die Desktop-Datei auszuführen, sondern führen Sie die Datei aus, auf die in der Desktop-Datei verwiesen wird.

Führen Sie beispielsweise /home/jsmith/Desktop/x11vnc.sh aus

Exec=/home/jsmith/Desktop/x11vnc.sh
1
user119824

Stellen Sie sicher, dass das Skript, auf das Ihre Desktop-Datei zeigt, auch ausführbar ist.

Wenn immer noch nicht funktioniert. Machen Sie die Desktop-Datei im Terminal lauffähig, indem Sie Terminal=true ändern und sie in ein Bash-Skript einfügen. Führen Sie das Skript aus, um die Fehlerausgabe abzufangen. Wechseln Sie zurück, wenn Fehler behoben sind.

0
hakunami

Die Antwort von Hamish ist großartig, aber ich würde gerne eine einfachere Alternative vorschlagen, bei der weniger Rohrleitungen erforderlich sind:

$(awk -F= '/^Exec/||/^TryExec/ {print $2;exit}' /usr/share/applications/firefox.desktop)

In diesem Fall sucht awk nach Zeilen, die mit Exec beginnen, und dann drucken wir einfach Felder nach dieser Zeile, wobei wir for loop und = Feld 2 drucken, dh, was danach kommt Feld. Die geschweiften Klammern an den Enden der Befehle, $(...), sind Parameterersetzungen, daher führt Shell den jeweils zurückgegebenen awk-Befehl aus. In diesem Fall wird der tatsächliche Befehl zurückgegeben, der nach Exec= folgt.

In einigen seltenen Fällen kann es mehr als ein = -Zeichen geben, was immer noch möglich ist. Dafür schlage ich vor

$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)
0