Правильный путь
Вы должны действительно использовать, 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. Если файл отсутствует или не является исполняемым, запись можно игнорировать (например, не использовать в меню).
Имея это в виду, не имеет смысла выполнять его значение.
Некоторые другие проблемы - Путь и Терминал . Путь состоит из рабочего каталога, в котором запускается программа. Terminal - логическое значение, указывающее, выполняется ли программа в окне терминала. Все это может быть решено, но нет смысла изобретать велосипед, поскольку уже есть реализации спецификации. Если вы хотите реализовать Path , имейте в виду, что он system()
порождает подпроцесс, поэтому вы не можете изменить рабочий каталог, выполнив что-то подобное system("cd \047" working_directory "\047"); system(command)
. Однако вы могли бы предположительно сделать что-то вроде system("cd \047" working_directory "\047 && " command)
. Примечание \ 047 - одинарные кавычки (поэтому команда не разбивается на пути с пробелами).
Альтернатива Python
Я краду страницу с Карло здесь , который предложил создать сценарий Python , чтобы использовать г модуля. Вот минимальный способ выполнить тот же код из оболочки без необходимости создавать файл и беспокоиться о вводе / выводе.
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
заключается в том, что это встроенная оболочка, а не двоичная команда.