it-swarm-tr.com

Terminalde bir .desktop dosyası çalıştırma

Toplayabildiğim kadarıyla, _.desktop_ dosyaları, uygulama ayarlarının özelleştirilmesine izin veren kısayollardır. Mesela _/usr/share/applications/_ klasörümde birçoğu var.

Eğer bu klasörü nautilus ile açarsam, bu uygulamaları sadece ilişkili dosyalarına çift tıklayarak çalıştırabilirim, örn. _firefox.desktop_ üzerine çift tıkladığınızda Firefox çalışır. Ancak aynı şeyi terminal üzerinden yapmanın bir yolunu bulamıyorum.

Eğer _gnome-open foo.desktop_ yaparsam, basitçe _foo.desktop_ bir metin dosyası olarak açılır. Çalıştırılabilir hale getirir ve sonra bash'de çalıştırırsam basitçe başarısız olur (beklenen, açıkça bash betiği değil).
EDIT: _exec /fullpath/foo.desktop_ yapmak, mülkiyeti kendim olarak değiştirsem bile bana bir _Permission denied_ mesajı verir. Çalıştırılabilir hale getirip aynı komutu uygularsam, kullandığım terminal sekmesi kapanır (sanırım çöküyor). Son olarak, eğer _Sudo exec /fullpath/foo.desktop_ yaparsam _Sudo: exec: command not found_ bildirirken bir hata alıyorum.

Benim sorum bu, terminalden bir _foo.desktop_ dosyasını nasıl çalıştırabilirim?

140
Malabarba

Çalıştırılan komut, masaüstü dosyasının içinde bulunur, bundan önce Exec= tarafından gelir, böylece şunu çıkartabilir ve çalıştırabilirsiniz:

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

Bunu yıkmak için

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

Bunu bir dosyaya koyabilirsin, içindekilerle ~/bin/deskopen

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

O zaman çalıştırılabilir yap

chmod +x ~/bin/deskopen

Ve sonra yapabilirsin, örneğin

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

Argümanlar (%u, %F etc) http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#exec) adresinde detaylandırılmıştır. -variables - hiçbiri komut satırında başlatmayla ilgili değil.

54
Hamish Downer

Cevap olmalı

xdg-open program_name.desktop

Ancak bir hata nedeniyle bu artık işe yaramaz.

83

gtk-launch'u destekleyen herhangi bir yeni ubuntu ile _, sadece basitçe gidin

gtk-launch <file>, .desktop bölümü olmayan .desktop dosyasının adıdır.

Böylece gtk-launch foo açılır foo.desktop

( gtk-launch belgeler )

.Desktop/usr/share/uygulamalarında,/usr/local/share/uygulamalarında veya ~/.local/share/uygulamalarında olmalıdır (- görünüşe göre istenirse .desktop kullanabilirsiniz.

Terminal veya alt + F2'den kullanılabilir (alt + F2 komutu tarihe çok kolay erişilebilir)

73
doug

Bugünden itibaren (12.10) böcek hala var. Aslında, gvfs-open (nasıl çalışır? [xdg-open] ile çalışır) bağlıdır.

Yine de hızlı bir çözüm buldum (nautilus kaynak kodundan ilham aldım). Biraz sarsılmış durumdadır, ancak Ubuntu 12.10'da kusursuz çalışır, Unity başlatıcısına anlamlı bir simge (daha fazla ?) eklemez.

İlk önce, Gio kullanarak bir python betiği yazdım ve onu ~/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)

Betik çalıştırılabilir izne sahip olmalı, bu yüzden bunu bir terminalde çalıştırdım:

chmod +x ~/bin/run-desktop

Sonra göreli .desktop girdisini ~/.local/share/applications/run-desktop.desktop üzerinde yarattım:

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

Sonunda girdiyi, ~/.local/share/applications/mimeapps.list bölümünün altındaki [Default Applications] öğesinde varsayılan işleyici olarak ilişkilendirdim:

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

Şimdi:

  • xdg-open something.desktop beklendiği gibi çalışıyor
  • #!/usr/bin/xdg-open çalıştırılabilir bir masaüstü girişinin üstünde hashbang da çalışıyor

gvfs-open, hatayı çözecekse, bu arada işe yaramaz bir iş olacak.

38
Carlo Pellegrini

Doğru yol

Varsa, gerçekten gtk-launch kullanıyor olmalısınız. Genellikle paketin bir parçasıdır libgtk-3-bin (bu durum dağıtıma göre değişebilir).

gtk-launch aşağıdaki gibi kullanılır:

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

Lütfen gtk-launch öğesinin . Desktop dosyasının yüklenmesini gerektirdiğini unutmayın (ör. /usr/share/applications veya ~/.local/share/applications).

Bu yüzden, bunun üstesinden gelmek için, başlatmadan önce istenen . Masaüstü dosyasını geçici olarak yükleyen, küçük bir Bash işlevi kullanabiliriz. . Desktop dosyasını kurmanın "doğru" yolu desktop-file-install aracılığıyladır, ancak bunu görmezden geleceğim.

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

    )

}

Bunun gibi kullanabilirsiniz (ve isterseniz ek argümanlar veya URI'ler boyunca da iletin):

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

Manuel Alternatif

Bir . Desktop dosyasını manuel olarak ayrıştırmak ve yürütmek istiyorsanız, bunu aşağıdaki awk komutuyla yapabilirsiniz:

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

awk komutunu hepsi bir arada bir komut dosyası gibi ele almak istiyorsanız; Bir hata mesajı bile gösterebilir ve Exec komutunun bulunamaması durumunda 1 dönüş koduyla çıkabilirsiniz:

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

Yukarıda belirtilen komutlar:

  1. ile başlayan satırı bulun Exec =
  2. Kaldır Exec =
  3. Tüm Exec değişkenlerini kaldırın (örneğin, %f, %u, %U). Şartnamenin öngördüğü şekilde bunları konumsal argümanlarla değiştirmek mümkündür, ancak bunu yapmak soruna önemli bir karmaşıklık katacaktır. En son Masaüstü Giriş Belirtimi bölümüne bakın.
  4. Komutu yürütün
  5. Hemen uygun çıkış koduyla çıkın (birden fazla Exec satırı çalıştırmayacak şekilde)

Not, bu AWK betiğinin diğer cevapların bazıları tarafından doğru bir şekilde ele alınabilecek veya cevaplanamayacağı birkaç Edge senaryosunu ele aldığını unutmayın. Özellikle, bu komut birden çok Exec değişkenini kaldırır (% sembolünün kaldırılmamasına dikkat ederek), yalnızca bir tek yürütür Exec line komutu ve Exec line komutu bir veya daha fazla eşittir işareti (ör. script.py --profile=name) içeriyorsa bile beklendiği gibi davranır.

Sadece bir kaç uyarı daha ... Şartnameye göre, TryExec :

Programın gerçekten yüklü olup olmadığını belirlemek için kullanılan, diskteki yürütülebilir bir dosyanın yolu. Yol mutlak bir yol değilse, dosya $ PATH ortam değişkeninde aranır. Dosya yoksa veya çalıştırılabilir değilse, giriş göz ardı edilebilir (örneğin menülerde kullanılmaz).

Bunu akılda tutarak, değerini uygulamak mantıklı değil.

Diğer bazı endişeler Yol ve Terminal . Yol programı çalıştırmak için kullanılan çalışma dizininden oluşur. Terminal , programın bir terminalde çalışıp çalışmadığını gösteren bir booleandir. penceresi. Bunların hepsi ele alınabilir, ancak teknik özelliklerin zaten uygulandığı gibi tekerleği yeniden icat etmenin bir anlamı yoktur. Yol uygulamak istiyorsanız, system() öğesinin bir alt işlem ortaya koyduğunu unutmayın, bu nedenle system("cd \047" working_directory "\047"); system(command) gibi bir şey yaparak çalışma dizinini değiştiremezsiniz. Ancak, muhtemelen system("cd \047" working_directory "\047 && " command) gibi bir şey yapabilirdiniz. Not\047 tek tırnak işaretidir (bu nedenle komut boşluklu yollarda kesilmez).

Python Alternatif

Carlo here 'dan bir sayfa çalıyorum, kim gi modülünü kullanmak için Python betiği oluşturmayı önerdi. İşte aynı kodu Shell'den bir dosya oluşturmadan ve G/Ç hakkında endişelenmenize gerek kalmadan yürütmenin minimal bir yolu.

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

}

Sonra başlatıcı işlevini aşağıdaki gibi yürütün:

launch ./path/to/shortcut.desktop

URI kullanımının isteğe bağlı olduğunu unutmayın. Ayrıca, herhangi bir hata kontrolü yapılmaz, böylece betiğinizin dayanıklı olmasını istiyorsanız, başlatıcının var olduğundan ve okunabilir olduğundan emin olmanız gerekir (kullanmadan önce).

31
Six

OP KDE hakkında soru sormazken, KDE çalıştıran herkes için aşağıdaki komut kullanılabilir:

kioclient exec <path-to-desktop-file>

Fedora'da bu, kde-runtime rpm'ye dahil edilir.

26
Raman

dex kullanabilirsiniz.

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

eğer exo-utils kurulu ise 13.10 sürümünde çalışıyor gibi görünüyor (Xubuntu'daki gibi).

13
jarno

Hamish'in cevabına yapılan ek.

Deskopen betiği göz önüne alındığında, referans karakteri hala # olduğundan, ona bir . Masaüstü dosyadaki Shebang satırı olarak bir başvuru kullanabilirsiniz. Yani --- bunu . Desktop dosyasının ilk satırı olarak koyun:

#!/usr/bin/env deskopen

Ardından . Desktop dosyasını çalıştırılabilir olarak işaretleyin (örneğin, bir chmod +x whatever.desktop ile) ve ardından

path/to/whatever.desktop

ve voilà - Uygulama açılacak! (Belirlediğim simge dosyasıyla tamamlayın, nasıl yapılacağı hakkında hiçbir fikrim yok.)

Şimdi, deskopen'in komut satırı parametrelerinden geçmesini istiyorsanız, bunun yerine hafifçe değiştirilmiş olan bu sürümü kullanabilirsiniz:

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

Bir kenara, shifting yerine "#{@:2}" kullanmaya çalıştım, ama bana 'kötü bir ikame' vermeye devam etti ...

8
pabst

Şu anda Ubuntu arşivlerinde anlattıklarınızı yapan bir uygulama yok. Bu XDG özellikleriyle uyumlu olmayan masaüstü ortamlarına (openbox gibi) entegrasyon sağlamak için genel bir çözüm oluşturmak için birkaç çaba var.

Arch Linux, python-xdg kütüphanelerine dayanan bir xdg-autostart uygulaması üzerinde çalışıyor. Bulabildiğim kadarıyla, bu henüz tam olarak tamamlanmadı, ancak bazı başarı raporları var.

Daha geniş kullanımdan faydalanacak olan bakıcı (xdg-autostart/) C++ uygulaması da (http://gitorious.org/xdg-autostart/) mevcuttur.

Çözümlerden herhangi biri sizin için işe yararsa, lütfen Debian veya Ubuntu’ya dahil edilmesi için gerekli çalışmaları göndermeyi düşünün.

Openstart ile her iki aracı da kullanmak için, /etc/xdg/openbox/autostart.sh içinde (openbox belgelerini doğru okuyorsam) çağırırsınız. Bu işe yaramazsa, muhtemelen herhangi bir openbox oturumu başlatma komut dosyalarından birini arayabilirsiniz.

6
Emmet Hikory

"standart bir komut kullanarak" gereksinimini karşılayan hemen bir çözümüm yok, ancak .desktop dosyalarını en az bir kez ayrıştıysanız veya istediyseniz Bash takma adı oluşturmak için aşağıdakiler çalışmalıdır:

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

ilginç olabilecek başka bir yaklaşım, binfmt-misc dosyalarında eşleşmekten daha çekirdek bir .desktop yöntemi oluşturmak olacaktır (şu anda etkinleştirdiğiniz kalıplar için grep -r . /proc/sys/fs/binfmt_misc/ bölümüne bakın).

Günün sonunda, bir yerde bir şey .desktop dosyalarını ayrıştırmak zorunda kalacak, bunun sadece "standart/varsayılan" olduğu sorusu.

6
sladen

Senaryoyu Carlo'sanswer üstünden aldım ve kendi masaüstü kullanımım için onu geliştirme girişiminde bulundum.

Komut dizisinin bu sürümü, herhangi bir uygulamayı HUD'a girmiş gibi, ilk sonuç olması muhtemel olduğu sürece çalıştırmanıza izin verir. Ayrıca, URI'leri desteklemeyen .desktop dosyaları için dosya argümanlarını iletmenizi sağlar.

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

(Burada çeşitli diğer cevaplardan derlenmiştir)

Sisteminize ve sisteminizde bulunabilecek veya bulunmayabilecek çeşitli hatalara bağlı olarak, bunlardan biri çalışana kadar aşağıdakileri deneyin:

  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

Ubuntu sistemlerinde, "başlat menüsü" masaüstü rampanızın /usr/share/applications/ içinde bulunduğunu unutmayın.

Örnek olarak, yukarıdaki komutlardan hangisinin Ubuntu 14.04 sistemimde çalıştığını veya çalışmadığını göstermek için, aşağıdaki benim için yapılan çağrıların sonuçları:

  1. xdg-open /usr/share/applications/Eclipse_for_cpp.desktop # Hata nedeniyle başarısız oluyor (bu .desktop dosyasını kaydetmemi sağlıyor)
  2. exo-open /usr/share/applications/Eclipse_for_cpp.desktop # Çalışır
  3. gtk-launch /usr/share/applications/Eclipse_for_cpp.desktop # "gtk-launch: böyle bir uygulama yok" ile başarısız oluyor
  4. kioclient exec /usr/share/applications/Eclipse_for_cpp.desktop # Çalışır
  5. dex /usr/share/applications/Eclipse_for_cpp.desktop # Başarısız, & Sudo apt install dex paketi dex'i bulamıyor
1
Gabriel Staples

Bu dosyaları sınamaya çalışırken, DM veya oturum yöneticisinin umduğum şeyi yapıp yapmadığını kontrol etmenin en basit yolunu buldum, bu işlemi UI klasör tarayıcısında çevreleyen klasörü açmak ve ardından açmak için çift tıklayın. .

Bir komut satırındaysanız: gvfs-open . veya gnome-open . yapılandırılmış klasör tarayıcısında açacaktır.

Baştan çıkarıcı şey, kaçışlar ve gerçekten alternatif davranış istemeyeceğiniz yerlerden alıntı yapmak gibi fiddly şeyler de dahil olmak üzere DM'nin davranışını yansıtmaz. Komut satırı değil, ancak bir şeyleri doğruladı. Ayrıca, Terminal=true ayarını hata ayıklama için kullanışlı buldum.

1
Danny Staple

Bu SO answer benim için netleştiren şeydi: masaüstü dosyasını yürütmeye çalışmayın, masaüstü dosyasında gösterilen dosyayı yürütün.

Örneğin, /home/jsmith/Desktop/x11vnc.sh dosyasını yürütün

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

Masaüstü dosyanızın işaret ettiği komut dosyasının da çalıştırılabilir olduğundan emin olun.

Hala işe yaramazsa. Terminal=true değerini değiştirerek masaüstü dosyasını terminalde çalıştırılabilir duruma getirin ve bir bash betiğine yerleştirin. Hata çıktısını yakalamak için betiği çalıştırın. Hatalar düzeltildiğinde geri değiştirin.

0
hakunami

Hamish'in cevabı harika, ancak daha az boru bağlantısıyla daha basit bir alternatif önermek istiyorum:

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

Bu durumda, awk, Exec ile başlayan satırı arar ve sonra sadece bu satırdan sonra alanları yazdırırız, döngü ve = kullanarak, 2 alanını basarız, yani bundan sonra ne gelirse alan. Komutların uçlarındaki küme parantezleri, $(...), parametre ikamesidir, bu nedenle Shell, awk komutunun döndürdüğü her şeyi yerine getirir; Bu durumda, Exec= den sonra gelen gerçek komutu döndürür.

Bazı nadir durumlarda birden fazla = işareti olabilir, bu hala bir olasılıktır. Bunun için öneriyorum

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