it-swarm.dev

Spuštění souboru .desktop v terminálu

Z toho, co mohu shromáždit, .desktop soubory jsou zkratky, které umožňují přizpůsobení nastavení aplikace. Například je jich mám v mé /usr/share/applications/ složka.

Pokud tuto složku otevřím v nautilus, mohu tyto aplikace spustit pouze dvojitým kliknutím na příslušný soubor, např. dvojité kliknutí firefox.desktop spustí Firefox. Nemohu však najít způsob, jak udělat totéž prostřednictvím terminálu.

Pokud ano gnome-open foo.desktop jednoduše se otevře foo.desktop jako textový soubor. Pokud to učiním spustitelným a poté spustím v bash, jednoduše to selže (což se očekává, není to zjevně bash skript).
ÚPRAVA: Doing exec /fullpath/foo.desktop mi dává Permission denied zpráva, i když si změním vlastnictví na sebe. Pokud provedu spustitelný soubor a provedu stejný příkaz, karta terminálu, kterou používám, se jednoduše zavře (hádám, že dojde k chybě). Nakonec, pokud ano Sudo exec /fullpath/foo.desktop, Dostávám hlášení o chybě Sudo: exec: command not found.

To je moje otázka, jak mohu spustit foo.desktop soubor z terminálu?

158
Malabarba

Příkaz, který je spuštěn, je obsažen uvnitř souboru na ploše, kterému předchází Exec=, abyste to mohli extrahovat a spustit:

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

Rozbít to

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

Dalo by se to vložit do souboru, řekněme ~/bin/deskopen s obsahem

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

Pak je spustitelný

chmod +x ~/bin/deskopen

A pak byste mohli udělat, např.

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

Argumenty (%u, %F atd.) jsou podrobné zde . Žádný z nich není relevantní pro spuštění na příkazovém řádku.

56
Hamish Downer

Odpověď by měla být

xdg-open program_name.desktop

Ale kvůli chyba ( zde na proti proudu) to už nefunguje.

91
Richard Holloway

gtk-launch

S jakýmkoli nedávným Ubuntu, který podporuje gtk-launch Prostě jděte

gtk-launch <file>

Kde je název souboru .desktop S částí .desktop Nebo bez ní. Otevře se gtk-launch foofoo.desktop

Od gtk-launchdokumentace :

gtk-launch spustí aplikaci s daným jménem. Pokud není uvedeno jinak, aplikace se spustí se správným oznámením o spuštění na výchozí obrazovce.

gtk-launch bere alespoň jeden argument, název spouštěné aplikace. Název by měl odpovídat názvu souboru na ploše aplikace tak, jak je umístěn v/usr/share/application , s nebo bez přípony '.desktop' .

.desktop By měl být v /usr/share/applications, /usr/local/share/applications Nebo ~/.local/share/applications.

Použitelné z terminálu nebo Alt + F2 (Alt + F2 ukládá příkaz do historie, takže je snadno přístupný).

82
doug

K dnešnímu dni (12.10) chyba je stále přítomen. Ve skutečnosti záleží na tom, jak gvfs-open (voláno xdg-open) funguje.

Přesto jsem zvládl rychlé řešení (odcizení inspirace ze zdrojového kódu nautilus). Je to trochu spletité, ale na Ubuntu 12.10 funguje bezchybně a přidává smysluplnou ikonu (nic víc ?) na launcheru Unity.

Nejprve jsem pomocí Gio napsal skript python) a uložil jej jako ~/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 __name__ == "__main__":
    main(*sys.argv)

Skript musí mít spustitelné oprávnění, takže jsem to spustil v terminálu:

chmod +x ~/bin/run-desktop

Pak jsem vytvořil relativní .desktop záznam na ~/.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

Nakonec jsem přidal položku jako výchozí popisovač v ~/.local/share/applications/mimeapps.list pod [Default Applications] sekce jako:

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

Nyní:

  • xdg-open něco.desktop funguje podle očekávání
  • #!/usr/bin/xdg-open hashbang na vrcholu spustitelného záznamu na ploše funguje také

Bude to k ničemu, když gvfs-open vyřeší chybu, ale mezitím ...

38
Carlo Pellegrini

Správná cesta

Pokud je k dispozici, měli byste opravdu používat gtk-launch. Obvykle je součástí balíčku libgtk-3-bin (to se může lišit podle distro).

gtk-launch Se používá takto:

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

Vezměte prosím na vědomí, že gtk-launch Vyžaduje, aby byl nainstalován soubor . Desktop (tj. Umístěn v /usr/share/applications Nebo ~/.local/share/applications).

Abychom to obešli, můžeme použít malou hackerskou funkci Bash, která před spuštěním dočasně nainstaluje požadovaný soubor . Desktop. "Správný" způsob instalace souboru . Desktop je přes desktop-file-install, Ale budu to ignorovat.

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

    )

}

Můžete jej použít takto (a také předat další argumenty nebo URI, pokud chcete):

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

Manuální alternativa

Pokud chcete ručně analyzovat a spustit soubor . Desktop, můžete tak učinit pomocí následujícího příkazu awk:

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

Pokud chcete zacházet s příkazem awk jako skript all-in-one; můžeme dokonce zobrazit chybovou zprávu a ukončit návratovým kódem 1 v případě, že příkaz Exec nebyl nalezen:

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

Výše uvedené příkazy:

  1. Najděte řádek začínající na Exec =
  2. Odebrat Exec =
  3. Odstraňte všechny proměnné Exec (např. %f, %u, %U). Je možné je nahradit pozičními argumenty, jak má specifikace v úmyslu, ale přidáním tohoto problému by se problém výrazně zvýšil. Viz nejnovější Specifikace položky na ploše .
  4. Proveďte příkaz
  5. Okamžitě ukončete s příslušným výstupním kódem (aby nedošlo k provedení více Exec řádků)

Všimněte si, že tento skript AWK řeší několik případů Edge, které mohou nebo nemusí být správně vyřešeny některými dalšími odpověďmi. Konkrétně tento příkaz odstraní více proměnných Exec (dávejte pozor, abyste jinak neodstránili symbol%), provede pouze jediný příkaz Exec řádek a bude se chovat podle očekávání, i když příkaz Exec line obsahuje jeden nebo více znaménků se rovná (např. script.py --profile=name).

Jen několik dalších upozornění ... Podle specifikace TryExec je:

Cesta ke spustitelnému souboru na disku použitém k určení, zda je program skutečně nainstalován. Pokud cesta není absolutní, soubor se vyhledá v proměnné prostředí $ PATH. Pokud soubor není k dispozici, nebo pokud není spustitelný, může být položka ignorována (nepoužívá se například v nabídkách).

S ohledem na to nemá smysl vykonávat svou hodnotu.

Některé další obavy jsou Cesta a Terminál. Cesta se skládá z pracovního adresáře, ve kterém se program spouští. Terminál je booleovský kód, který označuje, zda je program spuštěn v okně terminálu. To vše lze řešit, ale nemá smysl znovuobjevovat kolo, protože již existují implementace specifikace. Pokud chcete implementovat Path, mějte na paměti, že system() vytváří podproces, takže nemůžete změnit pracovní adresář tím, že uděláte něco jako system("cd \047" working_directory "\047"); system(command). Pravděpodobně byste však mohli udělat něco jako system("cd \047" working_directory "\047 && " command). Poznámka\047 jsou jednoduché uvozovky (takže příkaz se nerozbije na cestách s mezerami).

The Python Alternative)

Ukradl jsem stránku z Carla zde , který navrhl vytvoření skriptu Python skript pro použití modulu gi. Zde je minimální způsob, jak provést stejný kód z prostředí Shell, aniž byste museli vytvářet soubor a starat se o V/V.

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

}

Poté spusťte funkci spouštěče následujícím způsobem:

launch ./path/to/shortcut.desktop

Použití URI je volitelné. Také se neprovádí žádná kontrola chyb, takže budete chtít zajistit, aby spouštěč existoval a aby byl čitelný (před použitím), pokud chcete, aby byl skript odolný.

32
Six

Zatímco OP se neptal na KDE, pro každého, kdo provozuje KDE, lze použít následující příkaz:

kioclient exec <path-to-desktop-file>

Na Fedoře je toto zahrnuto do kde-runtime rpm.

28
Raman

Můžete použít dex .

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

zdá se, že funguje ve verzi 13.10, pokud jsou nainstalovány exo-utils (jako je tomu v případě Xubuntu).

16
jarno

Dodatek k Hamishově odpovědi.

Vzhledem k skriptu deskopen můžete použít odkaz na něj jako řádek Shebang v souboru . Desktop, protože znak komentáře je stále #. To znamená, že to uveďte jako první řádek souboru . Desktop:

#!/usr/bin/env deskopen

Pak označte soubor . Desktop jako spustitelný soubor (např. Pomocí chmod +x whatever.desktop) a pak můžete

path/to/whatever.desktop

a voilà - Aplikace se otevře! (Kompletní se souborem ikon, který jsem uvedl, i když netuším jak.)

Nyní, pokud také chcete, aby deskopen procházel všemi parametry příkazového řádku, můžete místo toho použít tuto mírně upravenou verzi:

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

Kromě toho jsem se pokusil použít "#{@:2}" místo shifting, ale stále mi dával „špatnou substituci“ ...

8
pabst

V současné době neexistuje žádná aplikace, která by dělala to, co popisujete v archivech Ubuntu. Probíhá několik snah o vytvoření obecného řešení, které zajistí integraci desktopových prostředí (jako je openbox), které nejsou v souladu s těmito specifikacemi XDG.

Arch Linux pracuje na implementaci xdg-autostartu založeného na knihovnách python-xdg. Z toho, co mohu najít, to vypadá, že ještě není úplně kompletní, ale má některé zprávy o úspěchu.

K dispozici je také C++ implementace xdg-autostart na gitorious (http://gitorious.org/xdg-autostart/), která by pravděpodobně měla prospěch z širšího využití.

Pokud pro vás některé řešení funguje, zvažte prosím odeslání potřebné práce k zařazení do Debian nebo Ubuntu.

Chcete-li použít některý z nástrojů s openstartem, měli byste jej nazvat v /etc/xdg/openbox/autostart.sh (pokud čtu dokumentaci openboxu správně). Pokud to nepomůže, pravděpodobně to můžete nazvat v kterémkoli skriptu inicializace relace openboxu.

6
Emmet Hikory

Nemám okamžité řešení, které by splňovalo požadavek na „pomocí standardního příkazu“, ale pokud jste chtěli minimálně analyzovat soubory .desktop Nebo chcete vytvořit alias Bash, pak by mělo fungovat následující:

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

jiným přístupem, který by mohl být zajímavý, by bylo vytvoření metody binfmt-misc na úrovni jádra než shody na souborech .desktop (viz vzory grep -r . /proc/sys/fs/binfmt_misc/ pro ty vzory, které jste aktuálně povolili).

Na konci dne bude něco někde muset analyzovat soubory .desktop, Je to jen otázka, jak "standardní/výchozí" to je.

6
sladen

(Sestaveno z různých dalších odpovědí zde)

V závislosti na vašem systému a různých chybách, které mohou nebo nemusí ve vašem systému existovat, zkuste následující, dokud některá z nich nefunguje:

  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

V systémech Ubuntu jsou spouštěče stolních počítačů „nabídky Start“ dostupné v /usr/share/applications/.

Jako příklad lze uvést, které z výše uvedených příkazů v mém systému Ubuntu 14.04 fungují nebo nefungují, zde jsou výsledky následujících volání pro mě:

  1. xdg-open /usr/share/applications/Eclipse_for_cpp.desktop # Selhání z důvodu chyby (pokusí se mě uložit tento soubor .desktop)
  2. exo-open /usr/share/applications/Eclipse_for_cpp.desktop # Funguje
  3. gtk-launch /usr/share/applications/Eclipse_for_cpp.desktop # Selže s "gtk-launch: žádná taková aplikace"
  4. kioclient exec /usr/share/applications/Eclipse_for_cpp.desktop # Funguje
  5. dex /usr/share/applications/Eclipse_for_cpp.desktop # Selhání a Sudo apt install dex nemůže najít balíček dex
3
Gabriel Staples

Vzal jsem skript z Carlo'sanswer výše a pokusil jsem se o něj vylepšit pro vlastní použití na ploše.

Tato verze skriptu vám umožní spouštět jakoukoli aplikaci, jako byste ji zadali na HUD, pokud to bude pravděpodobně první výsledek. Umožňuje také předávat argumenty pro soubory .desktop, které nepodporují 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 __name__ == "__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

Při pokusu o testování těchto souborů jsem našel nejjednodušší způsob, jak zkontrolovat, že DM nebo správce relací by udělal to, co jsem očekával) bylo otevřít okolní adresář v prohlížeči složek UI a potom poklepat otevřít je.

Pokud jste na příkazovém řádku: gvfs-open . nebo gnome-open . ji otevře v konfigurovaném prohlížeči složek.

Sedm nebude zrcadlit chování DM, včetně chmurných věcí, jako jsou úniky a citace, kde byste opravdu nechtěli alternativní chování. Nejedná se o příkazový řádek, ale ověří to. Také jsem našel nastavení Terminal=true užitečné pro ladění.

1
Danny Staple

Toto SO odpověď je to, co mi to objasnilo: nesnažte se spustit soubor na ploše, spusťte soubor, na který je uveden v souboru na ploše.

Například spusťte /home/jsmith/Desktop/x11vnc.sh

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

Ujistěte se, že skript, na který odkazuje soubor na ploše, je také spustitelný.

Pokud stále nefunguje. Změnit _ [Učinit soubor plochy spustitelný v terminálu změnou Terminal=true, a vložte ji do bash skriptu. Spusťte skript pro zachycení chybového výstupu. Při opravě chyb se vraťte zpět.

0
hakunami

Hamishova odpověď je skvělá, ale ráda bych navrhla jednodušší alternativu s menším zapojením:

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

V tomto případě awk vyhledá řádek začínající Exec a poté jednoduše vytiskneme pole za tímto řádkem, pomocí smyčky a = Vytiskneme pole 2, tj. Cokoli přichází po tomto poli. Kudrnaté závorky na koncích příkazů, $(...), jsou substituce parametrů, takže Shell provede jakékoli vrácené příkazy awk; v tomto případě vrací skutečný příkaz, který přichází po Exec=.

V ojedinělých případech může existovat více než jeden znak =, Což je stále možnost. Za to navrhuji

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