Правильний шлях
Ви дійсно повинні користуватися, 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
).
Тож, щоб обійти це, ми можемо використовувати хакерську маленьку функцію Bash, яка тимчасово встановлює потрібний файл .desktop перед його запуском. "Правильний" спосіб встановити .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
команди як до сценарію «все в одному»; ми навіть можемо показати повідомлення про помилку та вихід із кодом повернення 1, якщо команда Exec не знайдена:
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 містить один або більше знаків рівності (наприклад script.py --profile=name
).
Ще кілька застережень ... Відповідно до специфікації, TryExec є:
Шлях до виконуваного файлу на диску, який використовується для визначення того, чи програма фактично встановлена. Якщо шлях не є абсолютним шляхом, файл шукається у змінній середовища $ PATH. Якщо файл відсутній або він не виконується, запис може бути проігноровано (наприклад, не використовується в меню).
Зважаючи на це, не має сенсу виконувати це значення.
Деякі інші проблеми - " Шлях та термінал" . Шлях складається з робочого каталогу для запуску програми. Термінал є булевим, який вказує, чи запускається програма у вікні терміналу. З цим можна вирішити всі питання, але в винаході колеса немає сенсу, оскільки вже є реалізація специфікації. Якщо ви хочете реалізувати Path , майте на увазі, що він system()
породжує підпроцес, тому ви не можете змінити робочий каталог, зробивши щось подібне system("cd \047" working_directory "\047"); system(command)
. Однак, можливо, ви можете зробити щось на кшталт system("cd \047" working_directory "\047 && " command)
. Примітка \ 047 - це одиничні лапки (тому команда не розбивається на шляхи з пробілами).
Альтернатива Python
Я викрадаю сторінку від Карло тут , який запропонував створити сценарій Python, щоб використовувати модуль gi . Ось мінімальний спосіб виконання одного і того ж коду з оболонки без створення файлу та турботи про введення / виведення.
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
можете, тому що це вбудована оболонка, а не двійкова команда.