Запуск файла.desktop в терминале
Из того, что я могу собрать, .desktop
файлы - это ярлыки, которые позволяют настраивать параметры приложения. Например, у меня их много в моем /usr/share/applications/
папка.
Если я открою эту папку в nautilus
Я могу запустить эти приложения, просто дважды щелкнув соответствующий файл, например, дважды щелкнув firefox.desktop
запускает Firefox Тем не менее, я не могу найти способ сделать то же самое через терминал.
Если я сделаю gnome-open foo.desktop
это просто открывается foo.desktop
в виде текстового файла. Если я делаю его исполняемым, а затем запускаю его в bash, он просто перестает работать (что, как ожидается, явно не bash-скрипт).
РЕДАКТИРОВАТЬ: Делать exec /fullpath/foo.desktop
дает мне Permission denied
сообщение, даже если я поменяю владельца на себя. Если я выполняю исполняемый файл и выполняю ту же команду, вкладка терминала, которую я использую, просто закрывается (полагаю, она вылетает). Наконец, если я сделаю sudo exec /fullpath/foo.desktop
Я получаю сообщение об ошибке sudo: exec: command not found
,
Это мой вопрос, как я могу запустить foo.desktop
файл с терминала?
20 ответов
Команда, которая запускается, содержится в файле рабочего стола, которому предшествует Exec=
так что вы можете извлечь и запустить это:
`grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &
Чтобы сломать это
grep '^Exec' filename.desktop - finds the line which starts with Exec
| tail -1 - only use the last line, in case there are multiple
| sed 's/^Exec=//' - removes the Exec from the start of the line
| sed 's/%.//' - removes any arguments - %u, %f etc
| sed 's/^"//g' | sed 's/" *$//g' - removes " around command (if present)
`...` - means run the result of the command run here
& - at the end means run it in the background
Вы можете положить это в файл, скажем, ~/bin/deskopen
с содержанием
#!/bin/sh
`grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g'` &
Затем сделайте его исполняемым
chmod +x ~/bin/deskopen
И тогда вы могли бы сделать, например,
deskopen /usr/share/applications/ubuntu-about.desktop
Аргументы (%u
, %F
и т.д.) подробно описаны по адресу http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html - ни один из них не имеет отношения к запуску из командной строки.
С любой недавней Ubuntu, которая поддерживает gtk-launch
просто иди
gtk-launch <file>
где имя файла.desktop без .desktop
часть
Так gtk-launch foo
открывает foo.desktop
(gtk-launch
документация)
.Desktop должен находиться в / usr / share / Applications, / usr / local / share / application или ~ /.local / share / Applications (очевидно, вы можете использовать.desktop, если хотите.
Используется из терминала или alt+F2 (команда alt + F2 хранит историю, поэтому легко доступна)
На сегодняшний день (12.10) ошибка все еще присутствует. На самом деле это зависит от того, как gvfs-open
(вызывается xdg-open
) работает.
Тем не менее, мне удалось быстро обойти (украсть вдохновение из исходного кода nautilus). Это немного запутанно, но работает безупречно на Ubuntu 12.10, добавляя значащий значок (не более ?
) на пусковой установке Unity.
Во-первых, я написал скрипт на 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
что-то.дескопт работает как положено#!/usr/bin/xdg-open
hashbang поверх исполняемой записи рабочего стола тоже работает
Это будет бесполезная работа, когда gvfs-open
решит ошибку, а пока...
Хотя OP не спрашивал о KDE, для всех, кто работает с KDE, можно использовать следующую команду:
kioclient exec <path-to-desktop-file>
На Fedora это включено в kde-runtime
оборотов в минуту.
Правильный путь
Вы действительно должны использовать 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 для использования модуля 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 необязательно. Кроме того, проверка ошибок не выполняется, поэтому вы должны убедиться, что модуль запуска существует и доступен для чтения (перед его использованием), если вы хотите, чтобы ваш сценарий был надежным.
exo-open [[path-to-a-desktop-file]...]
Кажется, работает в выпуске 13.10, если exo-utils установлен (как в случае с Xubuntu).
(Составлено из различных других ответов здесь)
В зависимости от вашей системы и различных ошибок, которые могут или не могут существовать в вашей системе, попробуйте следующее, пока одна из них не сработает:
xdg-open program_name.desktop
exo-open program_name.desktop
gtk-launch program_name.desktop
kioclient exec program_name.desktop
dex program_name.desktop
Обратите внимание, что в системах Ubuntu ваши пусковые установки рабочего стола "меню пуск" доступны в /usr/share/applications/
,
В качестве примера, чтобы показать, какие из перечисленных выше команд работают или не работают в моей системе Ubuntu 14.04, вот результаты следующих вызовов для меня:
xdg-open /usr/share/applications/eclipse_for_cpp.desktop
# Сбой из-за ошибки (пытается сохранить этот файл.desktop)exo-open /usr/share/applications/eclipse_for_cpp.desktop
# Работаетgtk-launch /usr/share/applications/eclipse_for_cpp.desktop
# Сбой с "gtk-launch: нет такого приложения"kioclient exec /usr/share/applications/eclipse_for_cpp.desktop
# Работаетdex /usr/share/applications/eclipse_for_cpp.desktop
# Сбой &sudo apt install dex
не могу найти пакет dex
Приложение к ответу Хэмиша.
Имея скрипт deskopen, вы можете использовать ссылку на него как строку shebang в файле .desktop, так как символ комментария по-прежнему #
, То есть, поместите это в качестве первой строки файла .desktop:
#!/usr/bin/env deskopen
Затем пометьте файл .desktop как исполняемый (например, chmod +x whatever.desktop
), а затем вы можете
path/to/whatever.desktop
и вуаля - приложение откроется! (В комплекте с значком файла, который я указал, хотя я понятия не имею, как.)
Теперь, если вы также хотите, чтобы deskopen проходил через любые параметры командной строки, вы можете вместо этого использовать эту слегка измененную версию:
#!/bin/sh
desktop_file=$1
shift
`grep '^Exec' "${desktop_file}" | sed 's/^Exec=//' | sed 's/%.//'` "$@" &
В сторону, я пытался использовать "#{@:2}"
вместо shift
но это продолжало давать мне "плохую замену"...
У меня нет немедленного решения, отвечающего требованию "использования стандартной команды", но если вы хотите минимально разобрать .desktop
файлы или хотите создать псевдоним Bash, то должно работать следующее:
awk -F= '/Exec=/{system($2); exit}' foo.desktop
другой подход, который может быть интересным, будет создание уровня ядра binfmt-misc
метод, чем соответствует .desktop
файлы (см. grep -r . /proc/sys/fs/binfmt_misc/
для тех шаблонов, которые вы в данный момент включили).
В конце дня что- то где-то придется разбирать .desktop
файлы, это просто вопрос того, как это "стандарт / по умолчанию".
В настоящее время нет приложения, которое делает то, что вы описываете в архивах Ubuntu. В настоящее время предпринимается пара попыток создать общее решение, обеспечивающее интеграцию для сред рабочего стола (таких как openbox), которые не соответствуют этим спецификациям XDG.
Arch Linux работает над реализацией xdg-autostart на основе библиотек python-xdg. Из того, что я могу найти, это, кажется, еще не полностью завершено, но есть некоторые сообщения об успехе.
Существует также реализация xdg-autostart на gitorious на C++ (http://gitorious.org/xdg-autostart/), которая, вероятно, выиграет от более широкого использования.
Если какое-либо из решений подходит вам, пожалуйста, рассмотрите возможность отправки необходимой работы для включения в Debian или Ubuntu.
Чтобы использовать любой инструмент с openstart, вы должны вызвать его в /etc/xdg/openbox/autostart.sh (если я правильно читаю документацию openbox). Если это не работает, вы можете вызвать его в любом из сценариев инициализации сеанса openbox.
Я взял сценарий из ответа Carlo Pellegrini, приведенного выше, и попытался улучшить его для собственного использования на рабочем столе.
Эта версия скрипта позволит вам запускать любое приложение, как если бы вы вводили его в 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)
Этот SO ответ дал мне понять: не пытайтесь выполнить файл рабочего стола, запустите файл, указанный в файле рабочего стола.
Например, выполните /home/jsmith/Desktop/x11vnc.sh
Exec=/home/jsmith/Desktop/x11vnc.sh
Ответ Хэмиша великолепен, но я хотел бы предложить более простую альтернативу, с меньшим количеством задействованного трубопровода:
$(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)
Убедитесь, что скрипт, на который указывает файл вашего рабочего стола, также является исполняемым.
Если все еще не работает. Сделайте файл рабочего стола работающим в терминале, изменив Terminal=true
и поместите его в скрипт bash. Запустите скрипт, чтобы перехватить вывод ошибок. Вернитесь назад, когда ошибки будут исправлены.
компакт-диск /usr/доли/приложения gio запустить имя_программы .desktop
По моему опыту использования приведенных выше ответов, он не дает никакой полезной диагностической информации и немного вводит в заблуждение, сообщая «не найдено» как причину ошибки, а не реальную основную причину. Лучшее, что я смог придумать, это установить
rofi
с
sudo apt install rofi
а затем запустить его из терминала с помощью:
rofi -show drun
Затем я выбрал свое приложение с помощью его нечеткого поиска, и после нажатия ввода он фактически дал мне реальную причину, по которой файл *.desktop не запускался (в моем случае у меня были кавычки вокруг строки Exec в моем * файл .desktop).
Кто-нибудь знает, где находится исходный код? Это действительно похоже на то, что мы должны создать PR для предоставления более качественных и точных сообщений об ошибках, поскольку это кажется распространенной проблемой при поиске в сети.
Edit1: я нашел
gtk-launch
источник здесь
При попытке протестировать эти файлы я нашел самый простой способ проверить, что DM или менеджер сеансов будет делать то, что я ожидал, - открыть окружающий каталог в браузере папок пользовательского интерфейса, а затем дважды щелкнуть, чтобы открыть их.
Если вы находитесь в командной строке: gvfs-open .
или же gnome-open .
откроет его в настроенной папке браузера.
Функция sed не будет отражать поведение DM, включая такие странные вещи, как побеги и цитаты, где вы действительно не хотели бы альтернативного поведения. Это не командная строка, но она действительно проверяла вещи. Я также нашел настройки Terminal=true
полезно для отладки.
«Я использую Ubuntu 20.10 (Groovy Gorilla)»
Просто откройте терминал, а затем перейдите в ту папку, где находится файл .desktop, а затем введите
chmod +x (name of desktop file)
./(name of desktop file)