Из того, что я могу собрать, файлы .desktop - это ярлыки, которые позволяют настраивать настройки приложения. Например, у меня их много в папке /usr/share/applications/.
Если я открою эту папку в nautilus, я могу запустить эти приложения, просто дважды щелкнув соответствующий файл, например. двойной щелчок firefox.desktop запускает Firefox. Однако я не могу найти способ сделать то же самое через терминал.
Если я делаю gnome-open foo.desktop, он просто открывает foo.desktop в виде текстового файла. Если я делаю его исполняемым, а затем запускаю его в bash, он просто терпит неудачу (что ожидается, это явно не скрипт bash). EDIT: Выполнение exec /fullpath/foo.desktop дает мне сообщение Permission denied, даже если я перехожу к себе. Если я делаю исполняемый файл и выполняю ту же команду, вкладка терминала, которую я использую, просто закрывается (я предполагаю, что она сработает). Наконец, если я sudo exec /fullpath/foo.desktop, я получаю сообщение об ошибке sudo: exec: command not found.
Это мой вопрос, как я могу запустить файл foo.desktop с терминала?
Ответ должен быть
xdg-open program_name.desktop
Но из-за ошибки это больше не работает.
С любым недавним ubuntu, который поддерживает gtk-launch, просто перейдите в
gtk-launch <file> где имя файла .desktop без части .desktop
Итак gtk-launch foo открывает foo.desktop
Если <file> не находится в /usr/share/application или месте, где вы выполняете gtk-launch, команда gtk-launch <file> <uri>. (gtk-launch документация)
Используется с терминала или alt + F2 (alt + F2 сохраняет команду в истории так легкодоступной)
На сегодняшний день (12.10) ошибка все еще присутствует. Это действительно зависит от того, как работает gvfs-open (называемый xdg-open).
Тем не менее, мне удалось быстро обходное решение (крадущее вдохновение из исходного кода Nautilus). Это немного запутанно, но безупречно работает на Ubuntu 12.10, добавив значащую иконку (не более ?) в Unity launcher.
Сначала я написал скрипт python с помощью Gio и поместил его в качестве ~/bin/run-desktop:
#!/usr/bin/python
from gi.repository import Gio
import sys
def main(myname, desktop, *uris):
launcher = Gio.DesktopAppInfo.new_from_filename(desktop)
launcher.launch_uris(uris, None)
if __name__ == "__main__":
main(*sys.argv)
Скрипт должен иметь разрешение на выполнение, поэтому я запустил его в терминале:
chmod +x ~/bin/run-desktop
Затем я создал относительную запись .desktop на ~/.local/share/applications/run-desktop.desktop:
[Desktop Entry]
Version=1.0
Name=run-desktop
Exec=run-desktop %U
MimeType=application/x-desktop
Terminal=false
Type=Application
Наконец, я связал запись как обработчик по умолчанию в ~/.local/share/applications/mimeapps.list в разделе [Default Applications] как:
[Default Applications]
....
application/x-desktop=run-desktop.desktop
Теперь:
xdg-open something.desktop работает так, как ожидалось, [hashbang] поверх исполняемого файла рабочего стола тожеЭто будет бесполезная работа, когда gvfs-open решит ошибку, но в тем временем ...
Вы действительно должны использовать 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, которая временно устанавливает желаемый [d5 ] .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).
Просто несколько других предостережений ... Согласно спецификации, Exec :
Путь к исполняемый файл на диске, используемый для определения того, действительно ли программа установлена. Если путь не является абсолютным путем, файл просматривается в переменной среды $ PATH. Если файл отсутствует или если он не является исполняемым, запись может быть проигнорирована (например, не используется в меню).Имея это в виду, нет смысла исполнять его значение.
Некоторые другие проблемы - это Path и Exec . Путь состоит из рабочего каталога для запуска программы. Терминал - это логическое значение, указывающее, запускается ли программа в окне терминала. Все это можно решить, но нет смысла изобретать колесо, поскольку уже есть реализация спецификации. Если вы хотите реализовать Path, имейте в виду, что system() создает подпроцесс, поэтому вы не можете изменить рабочий каталог, выполнив что-то вроде system("cd \047" working_directory "\047"); system(command). Однако вы могли бы сделать что-то вроде system("cd \047" working_directory "\047 && " command). Примечание. \ 047 - одинарные кавычки (поэтому команда не разбивается на пути с пробелами).
Я краду страницу у Карло, которая предложила создать скрипт Python для использования модуля Path . Вот минимальный способ выполнить один и тот же код из оболочки без необходимости создавать файл и беспокоиться о вводе / выводе.
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 не является обязательным. Кроме того, проверка ошибок не выполняется, поэтому вы хотите убедиться, что пусковая установка существует и доступна для чтения (перед ее использованием), если вы хотите, чтобы ваш скрипт был долговечным.
Хотя OP не спрашивал о KDE, для тех, кто использует KDE, можно использовать следующую команду:
kioclient exec <path-to-desktop-file>
exo-open [[path-to-a-desktop-file]...]
, похоже, работает в версии 13.10, если exo-utils установлен (как в случае с Xubuntu).
Добавление к ответу Хэмиша.
Учитывая сценарий deskopen, вы можете использовать ссылку на него как строку shebang в Addendum to answer. file, так как комментарий символ все еще #. То есть, поставьте это как первую строку файла .desktop:
#!/usr/bin/env deskopen
Затем поместите файл .desktop в качестве исполняемого файла (например, с помощью chmod +x whatever.desktop) , а затем вы можете
path/to/whatever.desktop
и voilà - приложение откроется! (В комплекте с файлом значка, который я указал, хотя я понятия не имею, как это сделать.)
Теперь, если вы также хотите, чтобы deskopen проходил через любые параметры командной строки, вы можете вместо этого использовать эту слегка модифицированную версию:
#!/bin/sh
desktop_file=$1
shift
`grep '^Exec' "${desktop_file}" | sed 's/^Exec=//' | sed 's/%.//'` "$@" &
В стороне, я попытался использовать "#{@:2}" вместо shift ing, но он продолжал давать мне «плохую замену» ...
В настоящее время приложение не делает то, что вы описываете в архивах Ubuntu. В настоящее время предпринимаются усилия по созданию общего решения для интеграции в настольные среды (например, openbox), которые не соответствуют этим спецификациям XDG.
Arch Linux работает над внедрением xdg-autostart на основе в библиотеках python-xdg. Из того, что я могу найти, это кажется еще не полным, но имеет некоторые сообщения об успехе.
Существует также реализация xdg-autostart на C ++ на gitorious (http://gitorious.org/xdg- autostart /), который, вероятно, выиграет от более широкого использования.
Если какое-либо из решений работает для вас, рассмотрите вопрос о предоставлении необходимой работы для включения в Debian или Ubuntu.
Чтобы использовать любой инструмент с openstart, вы бы назвали его в /etc/xdg/openbox/autostart.sh (если я правильно читаю документацию Openbox). Если это не сработает, вы можете вызвать его в любом из скриптов инициализации сеанса openbox.
У меня нет немедленного решения, удовлетворяющего требованию «использовать стандартную команду», но если вы хотите минимально разобрать файлы .desktop или хотите создать псевдоним Bash, тогда должно работать следующее: [ ! d0] awk -F= '/Exec=/{system($2); exit}' foo.desktop
другой подход, который может быть интересным, - это создать метод binfmt-misc на уровне ядра, чем совпадения в файлах .desktop (см. grep -r . /proc/sys/fs/binfmt_misc/ для этих паттернов что вы в настоящее время активировали).
В конце дня «с помощью стандартной команды» где-то придется разбирать файлы .desktop, это всего лишь вопрос как «стандарт / значение по умолчанию».
При попытке протестировать эти файлы я нашел самый простой способ проверить, что DM или менеджер сеансов будут делать то, что я ожидал, чтобы открыть окружающий каталог в браузере папок пользовательского интерфейса, а затем дважды щелкните, чтобы открыть их.
Если вы находитесь в командной строке: gvfs-open . или gnome-open . откроют его в браузере настроенных папок.
. Команда sed не будет отражать поведение DM, в том числе такие вещи, как fiddy stuff убегает и цитирует, где вам действительно не хотелось бы альтернативного поведения. Это не командная строка, но она проверяет все. Я также нашел установку Terminal=true полезной для отладки.
Этот SO ответ на этот вопрос дал мне понять: не пытайтесь выполнить файл рабочего стола, выполните файл, указанный в файле рабочего стола.
Например, execute / home / jsmith / Рабочий стол / x11vnc.sh
Exec=/home/jsmith/Desktop/x11vnc.sh
Я взял сценарий из ответа Карло выше и попытался улучшить его для моего собственного использования на рабочем столе.
Эта версия скрипта позволит вам запускать любое приложение, как если бы вы ввели его на HUD, если это, скорее всего, первый результат. Он также позволяет передавать аргументы файла для файлов .desktop, которые не поддерживают URI.
#!/usr/bin/env python
from gi.repository import Gio
from argparse import ArgumentParser
import sys, os
def find_app(search_string):
for group in Gio.DesktopAppInfo.search(search_string):
for entry in group:
try:
return Gio.DesktopAppInfo.new(entry)
except: pass
return None
def main(args):
launcher = None
if os.path.isfile(args.appName):
try:
# If it's a file, do that first.
launcher = Gio.DesktopAppInfo.new_from_filename(args.appName)
except TypeError:
print "'" + args.appName + "' is not a .desktop file"
sys.exit(-1)
# If it's a .desktop file in the DB, try using that
if launcher is None and args.appName.endswith('.desktop'):
try:
launcher = Gio.DesktopAppInfo.new(args.appName)
except TypeError: pass
if launcher is None:
# Search for the app by the text given
launcher = find_app(args.appName)
if launcher is None:
print "No app named " + args.appName + " could be found"
sys.exit(-1)
if (launcher.supports_uris()):
launcher.launch_uris(args.uris, None)
elif (launcher.supports_files()):
launcher.launch(list({ Gio.File.parse_name(x) for x in args.uris }), None)
else :
launcher.launch()
if __name__ == "__main__":
argParser = ArgumentParser(description="Launch a .desktop file or application")
argParser.add_argument("appName",
help="the name of any application, a desktop file's basename, or a concrete path to a desktop file",
action='store'
)
argParser.add_argument("uris",
nargs='*',
help="Files or URIs to pass to the application"
)
args = argParser.parse_args()
main(args)
Убедитесь, что сценарий, на который указывает ваш рабочий стол, также является исполняемым.
Если все еще не работает. Сделайте рабочий стол рабочего стола в терминале, изменив Terminal=true и поместив его в сценарий bash. Запустите скрипт, чтобы поймать вывод ошибки. Замените ошибку, если исправлены ошибки.
Ответ Хэмиша велик, но я хотел бы предложить более простую альтернативу, с меньшим количеством задействованных труб:
$(awk -F= '/^Exec/||/^TryExec/ {print $2;exit}' /usr/share/applications/firefox.desktop)
В этом случае awk ищет строку начиная с Exec, а затем мы просто печатаем поля после этой строки, используя для цикла и = печатаем поле 2, т. е. все, что приходит после этого поля. Кудрявые скобки на концах команд $(...) - это замена параметров, поэтому shell будет выполнять любую команду awk; в этом случае возвращается фактическая команда, которая появляется после Exec=.
В некоторых редких случаях может быть более одного знака =, что по-прежнему возможно. Для этого я предлагаю
$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)