web-dev-qa-db-ja.com

ターミナルで.desktopファイルを実行する

私が収集できるものから、.desktopファイルは、アプリケーションの設定をカスタマイズできるショートカットです。たとえば、/usr/share/applications/フォルダーにはたくさんあります。

nautilusでそのフォルダーを開くと、関連するファイルをダブルクリックするだけでこれらのアプリケーションを実行できます。 firefox.desktopをダブルクリックすると、Firefoxが実行されます。ただし、ターミナルを介して同じことを行う方法が見つかりません。

gnome-open foo.desktopを実行すると、単にfoo.desktopがテキストファイルとして開きます。実行可能にしてからbashで実行すると、失敗するだけです(予想どおり、明らかにbashスクリプトではありません)。
編集:所有権を自分に変更しても、exec /fullpath/foo.desktopを実行するとPermission deniedメッセージが表示されます。実行可能ファイルを作成して同じコマンドを実行すると、使用しているターミナルタブが単純に閉じます(クラッシュすると推測します)。最後に、Sudo exec /fullpath/foo.desktopを実行すると、Sudo: exec: command not foundを報告するエラーが表示されます。

それが私の質問です。端末からfoo.desktopファイルを実行するにはどうすればよいですか?

140
Malabarba

実行されるコマンドはデスクトップファイル内に含まれており、先頭にExec=が付いているため、次の方法で抽出して実行できます。

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

それを壊すために

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

これをファイルに入れることができます。たとえば、~/bin/deskopenの内容を

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

次に、実行可能にします

chmod +x ~/bin/deskopen

そして、あなたは、例えばすることができます

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

引数(%u%Fなど)は http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#execで詳しく説明されています。 -variables -コマンドラインでの起動には関係ありません。

54
Hamish Downer

答えは

xdg-open program_name.desktop

しかし、 バグ により、これは機能しなくなりました。

83

gtk-launchをサポートする最近のUbuntuで

gtk-launch <file>ここで、.desktop部分を除いた.desktopファイルの名前

gtk-launch fooが開くfoo.desktop

gtk-launchドキュメント

.desktopは/ usr/share/applications、/ usr/local/share/applications、または〜/ .local/share/applicationsにある必要があります(必要に応じて.desktopを使用できます。

端末またはalt + F2から使用可能(alt + F2はコマンドを履歴に保存するので、簡単にアクセスできます)

73
doug

今日(12.10) バグ はまだ存在しています。実際には、gvfs-openxdg-openによって呼び出される)の機能に依存します。

それでも、私は簡単な回避策を管理しました(nautilusのソースコードからインスピレーションを盗みました)。少し複雑ですが、Ubuntu 12.10では問題なく機能し、Unityランチャーに意味のあるアイコン(?は不要)が追加されます。

まず、Gioを使用してpythonスクリプトを作成し、~/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)

スクリプトには実行権限が必要なので、これをターミナルで実行しました。

chmod +x ~/bin/run-desktop

次に、.desktopに相対~/.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

最後に、~/.local/share/applications/mimeapps.listセクションの下の[Default Applications]のデフォルトハンドラーとしてエントリを関連付けました。

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

今:

  • xdg-open something.desktopは期待どおりに動作します
  • #!/usr/bin/xdg-open実行可能デスクトップエントリの上にあるハッシュバングも機能します

gvfs-openがバグを解決するときは役に立たない作業になりますが、それまでは...

38

正しい方法

gtk-launchが使用可能であれば、実際に使用する必要があります。通常はパッケージの一部ですlibgtk-3-bin(これはディストリビューションによって異なる場合があります)。

gtk-launchは次のように使用されます。

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

gtk-launchでは、。desktopファイルをインストールする必要があります(つまり、/usr/share/applicationsまたは~/.local/share/applicationsにあります)。

そのため、これを回避するために、目的の。desktopファイルを起動する前に一時的にインストールする、ハックのような小さなBash関数を使用できます。 。desktopファイルをインストールする「正しい」方法はdesktop-file-installを経由しますが、それは無視します。

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

    )

}

次のように使用できます(必要に応じて追加の引数またはURIも渡します)。

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

手動の代替

。desktopファイルを手動で解析して実行する場合は、次のawkコマンドを使用して実行できます。

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

awkコマンドをオールインワンスクリプトのように扱いたい場合。エラーメッセージを表示して、Execコマンドが見つからない場合に戻りコード1で終了することもできます。

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

前述のコマンドは:

  1. Exec =で始まる行を見つけます
  2. 削除Exec =
  3. Exec変数をすべて削除します(例:%f%u%U)。仕様が意図するように、これらを位置引数に置き換えることは可能ですが、そうすることで問題がかなり複雑になります。最新の Desktop Entry Specification を参照してください。
  4. コマンドを実行する
  5. 適切な終了コードですぐに終了します(複数のExec行を実行しないように)

このAWKスクリプトは、他のいくつかの回答によって適切に対処される場合とされない場合がある少数のEdgeのケースに対処していることに注意してください。具体的には、このコマンドは複数のExec変数を削除し(%記号を削除しないように注意)、単一のExec行コマンド。Exec行コマンドに1つ以上の等号(例:script.py --profile=name)が含まれている場合でも、期待どおりに動作します。

いくつかの注意点...仕様によると、TryExecは次のとおりです。

プログラムが実際にインストールされているかどうかを判断するために使用されるディスク上の実行可能ファイルへのパス。パスが絶対パスでない場合、ファイルは$ PATH環境変数で検索されます。ファイルが存在しない場合、または実行可能でない場合、エントリは無視される場合があります(たとえば、メニューでは使用されません)。

それを念頭に置いて、その価値を実行することは意味がありません。

その他の懸念事項は、PathおよびTerminalです。 Pathは、プログラムを実行する作業ディレクトリで構成されます。Terminalは、プログラムが端末で実行されるかどうかを示すブール値です。窓。これらはすべて対処できますが、仕様の実装がすでにあるため、車輪を再発明する意味はありません。 Pathを実装する場合は、system()がサブプロセスを生成するので、system("cd \047" working_directory "\047"); system(command)のようなことを行って作業ディレクトリを変更できないことに注意してください。 。ただし、おそらくsystem("cd \047" working_directory "\047 && " command)のようなことができます。注\ 047は一重引用符です(したがって、コマンドはスペースを含むパスで中断しません)。

Pythonの代替

Carloからページを盗んでいます here 、彼はPythonスクリプトを作成してgiモジュールを使用することを提案しました。ファイルを作成してI/Oを心配することなく、シェルから同じコードを実行する最小限の方法を次に示します。

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

}

次に、次のようにランチャー関数を実行します。

launch ./path/to/shortcut.desktop

URIの使用はオプションです。また、エラーチェックは実行されないため、スクリプトを永続的にする場合は、ランチャーが存在し、(使用する前に)読み取り可能であることを確認する必要があります。

31
Six

OPはKDEについて尋ねていませんでしたが、KDEを実行している人は誰でも次のコマンドを使用できます。

kioclient exec <path-to-desktop-file>

Fedoraでは、これはkde-runtime rpmに含まれています。

26
Raman

dex を使用できます。

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

exo-utilsがインストールされている場合、Xubuntuの場合のように、13.10リリースで動作するようです。

13
jarno

ハミッシュの答えへの補遺。

Deskopenスクリプトを指定すると、コメント文字が#のままなので、。desktopファイルのShebang行としてそれへの参照を使用できます。つまり、これを。desktopファイルの最初の行として配置します。

#!/usr/bin/env deskopen

次に、。desktopファイルに実行可能としてフラグを付けます(たとえば、chmod +x whatever.desktopを使用)。

path/to/whatever.desktop

およびvoilà-アプリが開きます! (方法はわかりませんが、指定したアイコンファイルで完了します。)

また、deskopenでコマンドラインパラメーターを通過させる場合は、代わりにこのわずかに変更されたバージョンを使用できます。

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

余談ですが、shiftingの代わりに"#{@:2}"を使用しようとしましたが、それは「悪い置換」を与え続けました...

8
pabst

現在、Ubuntuアーカイブで説明したことを実行するアプリケーションはありません。これらのXDG仕様に準拠していないデスクトップ環境(openboxなど)に統合を提供する一般的なソリューションを作成するために、いくつかの取り組みが進行中です。

Arch Linuxは、python-xdgライブラリに基づいたxdg-autostartの実装に取り​​組んでいます。私が見つけることができるものから、これはまだ完全に完全ではないようですが、成功のいくつかの報告があります。

また、gitoriousでのxdg-autostartのC++実装(http://gitorious.org/xdg-autostart/)もあります。

どちらかの解決策が有効な場合は、DebianまたはUbuntuに含めるために必要な作業を提出することを検討してください。

Openstartでいずれかのツールを使用するには、/ etc/xdg/openbox/autostart.shで呼び出します(openboxのドキュメントを正しく読んでいる場合)。これが機能しない場合は、おそらくopenboxセッション初期化スクリプトのいずれかで呼び出すことができます。

6
Emmet Hikory

"using the standard command"の要件を満たす即時解決策はありませんが、.desktopファイルを最小限に解析したい場合、またはBashエイリアスを作成したい場合は、以下が機能するはずです:

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

興味深いかもしれない別のアプローチは、binfmt-miscファイルで一致するよりもカーネルレベルの.desktopメソッドを作成することです(現在有効にしているパターンについてはgrep -r . /proc/sys/fs/binfmt_misc/を参照してください)。

結局のところ、somethingどこかで.desktopファイルを解析する必要がありますが、それは単に「標準/デフォルト」がどのようになっているのかという問題です。

6
sladen

上記の Carlo'sanswer からスクリプトを取得し、自分のデスクトップで使用するためにスクリプトの改善を試みました。

このバージョンのスクリプトを使用すると、最初の結果である可能性が高い限り、HUDで入力したかのようにアプリを実行できます。また、URIをサポートしない.desktopファイルのファイル引数を渡すこともできます。

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

(他のさまざまな回答をここにまとめました)

システム、およびシステムに存在する場合と存在しない場合があるさまざまなバグに応じて、次のいずれかが機能するまで試してください。

  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システムでは、「[スタート]メニュー」デスクトップランチャーが/usr/share/applications/で利用できることに注意してください。

例として、上記のコマンドのどれが私のUbuntu 14.04システムで機能するか、または機能しないかを示すために、ここに私のための以下の呼び出しの結果があります:

  1. xdg-open /usr/share/applications/Eclipse_for_cpp.desktop#バグが原因で失敗します(この.desktopファイルを保存してください)
  2. exo-open /usr/share/applications/Eclipse_for_cpp.desktop#動作
  3. gtk-launch /usr/share/applications/Eclipse_for_cpp.desktop#「gtk-launch:no such application」で失敗する
  4. kioclient exec /usr/share/applications/Eclipse_for_cpp.desktop#動作
  5. dex /usr/share/applications/Eclipse_for_cpp.desktop#失敗、およびSudo apt install dexはパッケージdexを見つけることができません
1
Gabriel Staples

これらのファイルをテストするときに、DMまたはセッションマネージャーが期待どおりに動作することを確認する最も簡単な方法を見つけました。UIフォルダーブラウザーで周囲のディレクトリを開き、ダブルクリックして開きます。

コマンドラインを使用している場合:gvfs-open .またはgnome-open .は、構成済みのフォルダーブラウザーで開きます。

Sedの事柄は、エスケープのような厄介なものや、代替の振る舞いが本当に必要ない場所を引用するなど、DMの振る舞いを反映しません。コマンドラインではありませんが、検証を行いました。 Terminal=trueの設定もデバッグに役立つことがわかりました。

1
Danny Staple

この SOの答え がそれを明確にした理由です。デスクトップファイルを実行しようとせず、デスクトップファイルで指定されたファイルを実行してください。

たとえば、/ home/jsmith/Desktop/x11vnc.shを実行します

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

デスクトップファイルが指すスクリプトも実行可能であることを確認してください。

それでも動作しない場合。 Terminal=trueを変更してデスクトップファイルをターミナルで実行可能にし、bashスクリプト内に配置します。スクリプトを実行してエラー出力をキャッチします。エラーが修正されたら元に戻します。

0
hakunami

Hamishの答えは素晴らしいですが、より少ない配管でよりシンプルな代替案を提案したいと思います。

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

この場合、awkExecで始まる行を検索し、forループと=を使用して、その行の後にフィールドを印刷します。つまり、フィールド2を印刷します。フィールド。コマンドの末尾にある中括弧($(...))はパラメーター置換であるため、シェルはawkコマンドが返すものをすべて実行します。この場合、Exec=の後に来る実際のコマンドを返します。

まれに、複数の=記号が存在する場合がありますが、これは可能性です。そのために、私はお勧めします

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