Jalan yang benar
Anda harus benar-benar menggunakan gtk-launch
jika tersedia. Biasanya merupakan bagian dari paket libgtk-3-bin (ini mungkin berbeda-beda menurut distro).
gtk-launch
digunakan sebagai berikut:
gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name
Harap dicatat bahwa gtk-launch
memerlukan file .desktop untuk diinstal (yaitu terletak di /usr/share/applications
atau ~/.local/share/applications
)
Jadi untuk menyiasatinya, kita dapat menggunakan fungsi Bash kecil yang bersifat sementara yang menginstal sementara file .desktop yang diinginkan sebelum meluncurkannya. Cara "benar" untuk menginstal file .desktop adalah melalui desktop-file-install
tetapi saya akan mengabaikannya.
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
)
}
Anda dapat menggunakannya seperti itu (dan juga berikan argumen tambahan atau URI jika Anda mau):
launch PATH [URI...]
launch ./path/to/shortcut.desktop
Alternatif Manual
Jika Anda ingin mem-parsing dan mengeksekusi file .desktop secara manual , Anda dapat melakukannya dengan awk
perintah berikut :
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Jika Anda ingin memperlakukan awk
perintah seperti skrip all-in-one; kita bahkan dapat menampilkan pesan kesalahan dan keluar dengan kode pengembalian 1 jika perintah Exec tidak ditemukan:
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}}'
Perintah-perintah tersebut akan:
- Temukan baris yang dimulai dengan Exec =
- Hapus Exec =
- Hapus semua variabel Exec (misalnya
%f
, %u
, %U
). Dimungkinkan untuk mengganti ini dengan argumen posisional sesuai spesifikasi yang dimaksudkan, tetapi melakukan hal itu akan menambah kompleksitas yang signifikan pada masalah. Lihat Spesifikasi Entri Desktop terbaru .
- Jalankan perintah
- Segera keluar dengan kode keluar yang sesuai (agar tidak mengeksekusi beberapa baris Exec )
Catatan, skrip AWK ini membahas beberapa kasus tepi yang mungkin atau mungkin tidak ditangani dengan benar oleh beberapa jawaban lainnya. Secara khusus, perintah ini menghapus beberapa variabel Exec (berhati-hati untuk tidak menghilangkan simbol%), hanya akan mengeksekusi satu perintah baris Exec , dan akan berperilaku seperti yang diharapkan bahkan jika perintah baris Exec berisi satu atau lebih tanda sama dengan (misalnya script.py --profile=name
).
Hanya beberapa peringatan lainnya ... Menurut spesifikasi, TryExec adalah:
Path ke file yang dapat dieksekusi pada disk yang digunakan untuk menentukan apakah program tersebut benar-benar diinstal. Jika path bukan path absolut, file tersebut dicari dalam variabel lingkungan $ PATH. Jika file tidak ada atau jika tidak dapat dieksekusi, entri dapat diabaikan (misalnya, tidak digunakan dalam menu).
Dengan pemikiran itu, tidak masuk akal untuk mengeksekusi nilainya.
Beberapa masalah lain adalah Path dan Terminal . Path terdiri dari direktori kerja untuk menjalankan program. Terminal adalah boolean yang menunjukkan apakah program dijalankan di jendela terminal. Ini semua dapat diatasi, tetapi tidak ada gunanya menciptakan kembali roda karena sudah ada implementasi dari spesifikasi. Jika Anda ingin mengimplementasikan Path , perlu diingat bahwa system()
memunculkan subproses, sehingga Anda tidak dapat mengubah direktori kerja dengan melakukan sesuatu seperti system("cd \047" working_directory "\047"); system(command)
. Namun Anda mungkin bisa melakukan sesuatu seperti system("cd \047" working_directory "\047 && " command)
. Catatan \ 047 adalah tanda kutip tunggal (sehingga perintah tidak memecah jalur dengan spasi).
Alternatif Python
Saya mencuri halaman dari Carlo di sini , yang menyarankan untuk membuat skrip Python untuk menggunakan modul gi . Inilah cara minimal untuk mengeksekusi kode yang sama dari shell tanpa harus membuat file dan khawatir tentang 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
}
Kemudian jalankan fungsi launcher sebagai berikut:
launch ./path/to/shortcut.desktop
Perhatikan bahwa penggunaan URI bersifat opsional. Selain itu, tidak ada pemeriksaan kesalahan yang dilakukan sehingga Anda ingin memastikan peluncur ada dan dapat dibaca (sebelum menggunakannya) jika Anda ingin skrip Anda tahan lama.
exec
kegagalan Anda adalah karena exec mengganti proses yang sedang berjalan dengan proses yang Anda tentukan, jadi yang Anda lakukan adalah mencoba mengganti shell Anda dengan menjalankan desktop sebagai biner yang dikompilasi. Alasan Anda tidak bisasudo exec
karena itu adalah builtin shell dan bukan perintah biner.