Правильный Путь
Вы действительно должны использовать gtk-launch
если он доступен. Обычно это часть пакета libgtk-3-bin (это может варьироваться в зависимости от дистрибутива).
gtk-launch
используется следующим образом:
gtk-launch APPLICATION [URI...]gtk-launch app-name.desktopgtk-launch app-name
Пожалуйста, обратите внимание, что gtk-launch
требует, чтобы .рабочий стол файл, который будет установлен (т.е. находится в /usr/share/applications
или ~/.local/share/applications
).
Итак, чтобы обойти это, мы можем использовать небольшую хакерскую функцию Bash, которая временно устанавливает желаемый .рабочий стол файл перед его запуском. "Правильный" способ установки .рабочий стол файл находится через 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
Ручная альтернатива
Если вы хотите вручную проанализировать и выполнить .рабочий стол файл, вы можете сделать это с помощью следующего awk
команда:
awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop
Если вы хотите лечить awk
команда похожа на сценарий "все в одном"; мы даже можем показать сообщение об ошибке и завершить работу с кодом возврата 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 (например
%f
, %u
, %U
). Можно заменить их позиционными аргументами, как это предусмотрено спецификацией, но это значительно усложнило бы проблему. Смотрите последние новости Спецификация ввода рабочего стола.
- Выполните команду
- Немедленно завершите работу с соответствующим кодом выхода (чтобы не выполнять несколько Выполнение линии)
Обратите внимание, что этот сценарий AWK рассматривает несколько крайних случаев, которые могут быть или не быть должным образом рассмотрены в некоторых других ответах. В частности, эта команда удаляет несколько Выполнение переменных (соблюдая осторожность, чтобы в противном случае не удалить символ %), будет выполняться только один Выполнение строка команды, и будет вести себя так, как ожидалось, даже если Выполнение линейная команда содержит один или несколько знаков равенства (например script.py --profile=name
).
Просто еще несколько предостережений... В соответствии со спецификацией, Попробуйте выполнить является:
Путь к исполняемому файлу на диске, используемый для определения того, действительно ли установлена программа. Если путь не является абсолютным путем, файл ищется в переменной среды $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 - "$@" <<EOFimport sysfrom gi.repository import GioGio.DesktopAppInfo.new_from_filename(sys.argv[1]).launch_uris(sys.argv[2:])EOF}
Затем выполните функцию запуска следующим образом:
launch ./path/to/shortcut.desktop
Обратите внимание, что использование URI является необязательным. Кроме того, проверка ошибок не выполняется, поэтому вам нужно убедиться, что программа запуска существует и доступна для чтения (перед ее использованием), если вы хотите, чтобы ваш скрипт был долговечным.