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

117

Z toho co mohu shromáždit,.desktop souborů jsou zkratky umožňující přizpůsobení nastavení aplikace. Mám například mnoho ve složce/usr/share/applications/.

Pokud otevře tuto složku vnautilus, mohu spustit tyto aplikace pouze dvojitým kliknutím na příslušný soubor, např. poklepáním nafirefox.desktop se spouští prohlížeč Firefox. Nelze však najít způsob, jak dělat totéž prostřednictvím terminálu.

Pokud udělámgnome-open foo.desktop, jednoduše otevíráfoo.desktop jako textový soubor. Pokud to udělám spustitelný a pak jej spustit v bash, prostě selže (což se očekává, jasně to není bash script).
EDIT: Dělámexec /fullpath/foo.desktop mi dává zprávuPermission denied, i když změním vlastnictví na sebe. Pokud vytvořím spustitelný soubor a udělám stejný příkaz, terminálová karta, kterou používám, se jednoduše zavře (hádám, že se to zhroutí). Konečně, pokud udělámsudo exec /fullpath/foo.desktop, zobrazí se chyba hlášenísudo: exec: command not found.

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

    
dané Malabarba 04.10.2010 15:58

16 odpovědí

47

Spuštěný příkaz je uložen uvnitř souboru plochy, před ním jeExec=, takže jej můžete extrahovat a spustit pomocí:

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

Chcete-li to zlomit

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

Můžete to dát do souboru, řekněme~/bin/deskopen s obsahem

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

Spusťte spustitelný soubor

chmod +x ~/bin/deskopen

A pak byste to mohli udělat, např.

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

Argumenty (%u,%F etc) jsou podrobně popsány na adrese Odkaz - žádný z nich není relevantní pro spuštění na příkazovém řádku.

    
odpověděl Hamish Downer 04.10.2010 16:52
64

Odpověď by měla být

xdg-open program_name.desktop

Ale vzhledem k chybě to už nefunguje.

    
odpověděl Richard Holloway 04.10.2010 17:28
52

S jakýmkoli novým ubuntu, který podporujegtk-launch stačí jednoduše jít

gtk-launch <file> kde je název souboru .desktop bez složky.desktop

Takžegtk-launch foo otevíráfoo.desktop

Pokud<file> není v/usr/share/application, nebo místo, kde spouštítegtk-launch, je příkazgtk-launch <file> <uri>. (gtk-launch dokumentace )

Použitelný z terminálu nebo alt + F2 (alt + F2 ukládá příkaz v historii tak snadno dostupný)

    
odpověděl doug 02.12.2013 23:32
37

Dnešní (12.10) chyba stále existuje. Ve skutečnosti závisí na tom, jak%gvfs-open (nazvanýxdg-open) funguje.

Stále se mi podařilo rychlé řešení (krást inspiraci ze zdrojového kódu nautilus). Je to trochu komplikované, ale funguje bezchybně na Ubuntu 12.10 a přidává na spouštěcí jednotku Unity smysluplnou ikonu (více?).

Nejdříve jsem napsal skript Pythonu pomocí Gio a uložil ho 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 oprávnění k spustitelnému souboru, takže jsem jej spustil v terminálu:

chmod +x ~/bin/run-desktop

Potom 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řiřadil záznam jako výchozí obslužný program v~/.local/share/applications/mimeapps.list pod sekcí[Default Applications] jako:

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

Nyní:

  • xdg-open something.desktop pracuje podle očekávání
  • #!/usr/bin/xdg-open hashbang nad spustitelným záznamem počítače funguje příliš

Bude to zbytečná práce, kdyžgvfs-open vyřeší chybu, ale mezitím ...

    
odpověděl Carlo Pellegrini 11.01.2013 10:06
22

Správná cesta

Měli byste opravdu používatgtk-launch, pokud je k dispozici. Obvykle je součástí balíčku libgtk-3-bin (toto se může lišit podle distribuce).

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í, žegtk-launch vyžaduje instalaci souboru .desktop (tj. umístěný v/usr/share/applications nebo~/.local/share/applications).

Abychom se dostali kolem toho, můžeme použít hackish malou funkci Bash, která dočasně nainstaluje požadovaný soubor .desktop před spuštěním. Správný způsob instalace souboru .desktop je přesdesktop-file-install, ale ignoruji to.

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  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 "" 2>/dev/null || {
    [[  = *.desktop && -f  && -r  && -s  ]] || {
        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 "" "$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 jako takové (a pokud chcete, předáte další argumenty nebo URI):

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

Ruční alternativa

Chcete-li ručně analyzovat a spustit soubor .desktop , můžete tak učinit následujícím příkazemawk:

awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system(
awk 'BEGIN {command=""} /^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); command=
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

}
; 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 7%s7\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'
)}' app-name.desktop

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

launch ./path/to/shortcut.desktop

Výše ​​uvedené příkazy budou:

  1. Najděte řádek začínající Exec =
  2. Odstraňte Exec =
  3. Odstraňte libovolné proměnné Exec (např.%f,%u,%U). Je možné je nahradit pozičními argumenty podle specifikace, ale přitom by tento problém značně komplikoval. Podívejte se na nejnovější Specifikace pro zadání do počítače .
  4. Proveďte příkaz
  5. Okamžitě ukončete příslušným kódem ukončení (tak, aby nebyly provedeny více řádků Exec )

Všimněte si, že tento skript AWK se zabývá několika okrajovými případy, které mohou nebo nemusí být správně řešeny některými dalšími odpověďmi. Konkrétně tento příkaz odstraňuje více proměnných Exec (dbá na to, aby se symbol% ​​neztratil jinak), provede pouze příkaz Exec a bude se chovat podle očekávání, i když příkaz Exec obsahuje jeden nebo více znaménků rovných (např.script.py --profile=name).

Jen pár dalších upozornění ... Podle specifikace TryExec je:

  

Cesta k spustitelnému souboru na disku, který slouží k určení, zda je program skutečně nainstalován. Pokud cesta není absolutní cesta, soubor je vzhlédnut v proměnné prostředí $ PATH. Pokud soubor není přítomen nebo pokud není spustitelný, může být položka ignorována (například v nabídkách nebude použita).

S ohledem na to nemá smysl provést jeho hodnotu.

Některé další obavy jsou Cesta a Terminál . Cesta se skládá z pracovního adresáře pro spuštění programu. Terminál je boolean, který označuje, zda je program spuštěn v terminálovém okně. To vše může být řešeno, ale nemáme smysl objevovat kolo, protože již existují implementace spec. Pokud chcete implementovat Cesta , mějte na paměti, žesystem() spouští podproces, takže nemůžete změnit pracovní adresář tím, že uděláte něco jakosystem("cd 7" working_directory "7"); system(command). Nicméně pravděpodobně byste mohli udělat něco jakosystem("cd 7" working_directory "7 && " command). Poznámka \ 047 jsou jednoduché uvozovky (takže příkaz se nerozbije na cestách s mezerami).

Python Alternative

Kradnu stránku od společnosti Carlo zde , která navrhla vytvořit skript Pythonu pro použití > gi . Zde je minimální způsob, jak provést stejný kód z shellu, aniž byste museli vytvářet soubor a starat se o I / O.

%pr_dfe%

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

%pr_dfe%

Upozorňujeme, že použití URI je nepovinné. Také není provedena žádná kontrola chyb, takže budete chtít zajistit, aby spouštěč existuje a je čitelný (před použitím), pokud chcete, aby váš skript byl trvanlivý.

    
odpověděl Six 21.08.2015 21:33
19

Zatímco se OP neptal na KDE, pro kohokoli, kdo používá KDE, může být použit následující příkaz:

kioclient exec <path-to-desktop-file>

    
odpověděl Raman 23.02.2014 19:09
10

exo-open [[path-to-a-desktop-file]...]

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

    
odpověděl jarno 22.12.2013 16:45
10

Můžete použít dex .

dex foo.desktop
    
odpověděl couac 26.01.2015 00:17
8

Dodatek k odpovědi Hamishova.

Vzhledem k deskopen skriptu můžete použít odkaz na něj jako linku shebang v souboru .desktop , jelikož znak komentáře je stále#. To znamená, že je to první řádek souboru .desktop :

#!/usr/bin/env deskopen

Označte soubor .desktop jako spustitelný (např.chmod +x whatever.desktop) a pak můžete

path/to/whatever.desktop

a voilà - aplikace se otevře! (Vyplňte soubor s ikonami, který jsem zadal, i když nemám představu o tom, jak.)

Nyní, pokud chcete, aby desktopopen procházel parametry příkazového řádku, můžete místo toho použít tuto lehce upravenou verzi:

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

Jako stranou jsem se snažil použít"#{@:2}" namístoshift ing, ale stále mi dává "špatnou náhradu" ...

    
odpověděl pabst 09.02.2012 21:12
6

V současné době neexistuje žádná aplikace, která by popsala v archivu Ubuntu. Probíhá několik úsilí o vytvoření obecného řešení pro integraci desktopových prostředí (jako je openbox), které nejsou v souladu s těmito specifikacemi XDG.

Arch Linux pracuje na implementaci xdg-autostart založené na knihovnách python-xdg. Z toho, co najdu, se zdá, že to ještě není úplné, ale má nějaké zprávy o úspěchu.

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

Pokud vám jedno řešení pracuje, zváte, prosím, zadejte potřebnou práci pro začlenění do Debianu nebo Ubuntu.

Chcete-li použít nástroj s otevřeným startstarem, zavoláte jej /etc/xdg/openbox/autostart.sh (pokud čte správně dokumentaci openboxu). Pokud to nefunguje, můžete ji pravděpodobně nazvat v libovolném inicializačním skriptu relace openbox.

    
odpověděl Emmet Hikory 05.07.2011 07:08
6

Nemám okamžité řešení splňující 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ěl fungovat následující:

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

jiným přístupem, který by mohl být zajímavý, by bylo vytvořit metodubinfmt-misc na úrovni jádra než odpovídat.desktop souborů (pro ty vzory, které jste aktuálně povolili, vidítegrep -r . /proc/sys/fs/binfmt_misc/).

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

    
odpověděl sladen 09.07.2011 23:22
1

Při pokusu o testování těchto souborů jsem našel nejjednodušší způsob, jak zkontrolovat, že DM nebo správce relací by dělal to, co jsem očekával, že otevřete obklopující dir v prohlížeči prohlížečů UI a poté dvakrát klikněte na jeho otevření.

Pokud jste v příkazovém řádku:gvfs-open . nebognome-open . jej otevře v prohlížeči nakonfigurovaných složek.

Věc sed nebude odrážet chování DM, včetně fiddly věci jako útěky a citovat, kde byste opravdu nechtěli alternativní chování. Není to příkazová řádka, ale ověřila věci. Také jsem zjistil nastaveníTerminal=true užitečné pro ladění.

    
odpověděl Danny Staple 19.05.2014 17:20
1

Tato odpověď SO je pro mě jasná: nepokoušejte se spustit soubor plochy, spustit soubor ukázaný v souboru desktopu.

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

Exec=/home/jsmith/Desktop/x11vnc.sh
    
odpověděl user119824 27.06.2014 19:45
1

Vzal jsem si skript z Carlo's odpověď výše a pokoušel jsem se o to zlepšit pro vlastní použití počítače.

Tato verze skriptu vám umožní spustit libovolnou aplikaci, jako kdybyste ji zadali na HUD, pokud je to pravděpodobně první výsledek. Umožňuje také předat argumenty souborů 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)
    
odpověděl Fordi 18.09.2015 19:20
0

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

Pokud stále nefunguje. Vytvořte soubor běžící v terminálu změnouTerminal=true a vložte jej do bash skriptu. Spusťte skript a zachyťte chybový výstup. Změna zpět při opravě chyb.

    
odpověděl hakunami 26.03.2015 09:33
0

Hamishova odpověď je skvělá, ale chtěl bych navrhnout jednodušší alternativu s menšími potrubími:

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

V tomto případěawk hledá řádek začínající naExec a pak po křivce jednoduše vytiskneme pole, za použití smyčky a= vytiskneme pole 2, tj. co se objeví po tomto poli. Křivkové závorky na koncích příkazů,$(...), jsou nahrazení parametrů, takže shell provede jakýkoliv příkaz awk vrátí; v tomto případě vrátí skutečný příkaz, který přijde poExec=.

V některých ojedinělých případech může být více než jedno procento co_kde%, což je ještě možnost. Za to navrhuji

$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)
    
odpověděl Sergiy Kolodyazhnyy 21.08.2015 21:55