正しい方法
使用gtk-launch
可能であれば、実際に使用する必要があります。通常、パッケージlibgtk-3-binの一部です(これはディストリビューションによって異なる場合があります)。
gtk-launch
次のように使用されます。
gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
.desktopファイルをインストールgtk-launch
する必要があることに注意してください(つまり、またはにあります)。/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}}'
前述のコマンドは:
- Exec =で始まる行を見つけます
- Exec =を削除
- Exec変数(
%f
、%u
など%U
)を削除します。仕様が意図するようにこれらを位置引数に置き換えることは可能ですが、そうすることは問題をかなり複雑にします。最新のデスクトップエントリ仕様を参照してください。
- コマンドを実行する
- 適切な終了コードですぐに終了します(複数のExec行を実行しないように)
このAWKスクリプトは、他の回答のいくつかによって適切に対処される場合とされない場合があるいくつかのエッジケースに対処していることに注意してください。具体的には、このコマンドは複数のExec変数を削除し(%記号を削除しないように注意)、単一のExec行コマンドのみを実行し、Exec行コマンドに1つ以上の等号(例:)が含まれていても期待どおりに動作しscript.py --profile=name
ます。
いくつかの他の警告...仕様によると、TryExecは次のとおりです。
プログラムが実際にインストールされているかどうかを判断するために使用されるディスク上の実行可能ファイルへのパス。パスが絶対パスでない場合、ファイルは$ PATH環境変数で検索されます。ファイルが存在しない場合、または実行可能でない場合、エントリは無視される場合があります(たとえば、メニューでは使用されません)。
それを念頭に置いて、その価値を実行することは意味がありません。
その他の懸念事項はPathとTerminalです。パスは、プログラムを実行する作業ディレクトリで構成されます。ターミナルは、プログラムがターミナルウィンドウで実行されるかどうかを示すブール値です。これらはすべて対処できますが、仕様の実装がすでにあるため、車輪を再発明する意味はありません。Pathを実装したい場合system()
、サブプロセスが生成されることに注意してください。そのため、などの操作を行って作業ディレクトリを変更することはできませんsystem("cd \047" working_directory "\047"); system(command)
。ただし、おそらく次のようなことができますsystem("cd \047" working_directory "\047 && " command)
。注\ 047は一重引用符です(したがって、コマンドはスペースを含むパスで中断しません)。
Pythonの代替
ここでCarloからページを盗んでいます。彼はgiモジュールを利用するPythonスクリプトを作成することを提案しました。ファイルを作成して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の使用はオプションです。また、エラーチェックは実行されないため、スクリプトを永続的にする場合は、ランチャーが存在し、(使用する前に)読み取り可能であることを確認する必要があります。
exec
失敗した理由は、execが現在実行中のプロセスを指定したプロセスに置き換えるためです。そのため、デスクトップをコンパイル済みバイナリとして実行するようにシェルを置き換えようとしました。できなかった理由sudo exec
は、シェル組み込みコマンドであり、バイナリコマンドではないためです。