Вопрос Запуск файла .desktop в терминале


Из того, что я могу собрать, .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 файл с терминала?


116
2017-10-04 13:58


происхождения


NB: Причина, по которой ваша exec failed был вызван тем, что exec заменяет ваш текущий процесс процессом, указанным вами, поэтому вы решили заменить вашу оболочку на запуск рабочего стола в виде скомпилированного двоичного файла. Причина, по которой вы не могли sudo exec потому что это встроенная оболочка, а не двоичная команда. - Daenyth
Интересно, мне было интересно, почему это заставило вкладку закрыть. - Malabarba
Связанный: Файлы Hashbang для Gnome .desktop - ændrük
Понимаю, они обрабатывают файл .desktop. Спасибо вам за ссылку. - enzotib
модераторы: oops, думаю, я мог случайно это отметить, извините, если это так - Croad Langshan


ответы:


Выполняемая команда содержится внутри файла рабочего стола, которому предшествует 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#exec-variables - ни один из них не подходит для запуска в командной строке.


47
2017-10-04 14:52



Это дает лучший результат до сих пор, но иногда вызывает нежелательное поведение. Это происходит всякий раз, когда строка «Exec =» имеет аргумент типа% u или% i. Bash пытается передать эту строку как обычный аргумент. Например, grep '^Exec' firefox.desktop | sed 's/^Exec=//' открывает Firefox с вкладкой, которая загружает WWW.% u.com, - Malabarba
На данный момент я добавил вторую sed для удаления любых аргументов. Но я думаю, что может быть более «естественный» способ запустить его. - Malabarba
Я обновил свой ответ с дополнительным sed - я забыл, что файлы на рабочем столе могут иметь аргументы. - Hamish Downer
Вы должны добавить «tail -1» в трубу после «grep», так как «Exec =» может появляться несколько раз, и после этого должно выполняться только последнее появление. - daisy
-1: Это может работать для простых .desktop файлов, но он игнорирует записи типа Path= а также TryExec= что может повлиять на выполнение. Он также выполняет неправильные Exec= если файл содержит действия на рабочем столе («быстрые списки») - MestreLion


Ответ должен быть

xdg-open program_name.desktop

Но из-за Жук это больше не работает.


63
2017-10-04 15:28



WoW это все еще ошибка, много прогресса в xdg. exo-open указан как обходной путь, и он также открывает gedit. :( - Drew
@RichardHolloway: gnome-openделает не вызов xdg-open, это наоборот! Таким образом, проблема заключается в gvfs-open (преемник или gnome-open) - MestreLion
«больше не работает»? Этого никогда не было! xdg-open работает ассоциацией mimetype и .desktop файлы связаны с текстовыми редакторами, поскольку они являются подклассом текста - MestreLion
это настолько глупо (что нет разумного способа запуска файла Desktop из терминала) - Sam Watkins
Эта ошибка все еще существует? - Noitidart


С помощью любого недавнего 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 хранит команду в истории так легкодоступна)


52
2017-12-02 22:32



Так и работает в debian.
gtk-launch firefox.desktop ~ / .local / share / applications / запускает firefox просмотр каталога ~ / .local / share / applications / для меня. Кажется, что если вы были правы, firefox не должен был передавать каталог файла .desktop в качестве аргумента. На самом деле каталог, переданный в gtk-launch, не должен использоваться для поиска директории, содержащей файл .desktop (и на самом деле это не так) - Croad Langshan
Ура! Ответ, который работает! - Alicia


На сегодняшний день (12.10) баг все еще присутствует. Это зависит от того, как gvfs-open (вызванный xdg-open) работает.

Тем не менее, мне удалось быстро обходное решение (украсть вдохновение из исходного кода Nautilus). Это немного запутанно, но безупречно работает на Ubuntu 12.10, добавляя значащую иконку (не более ?) на пусковой установке «Единство».

Во-первых, я написал скрипт 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 работает как ожидалось
  • #!/usr/bin/xdg-open hashbang поверх исполняемого рабочего стола тоже работает

Это будет бесполезная работа, когда gvfs-open решит ошибку, но тем временем ...


37
2018-01-11 09:06



Это работает лучше, чем Ответ Хэмиш Даунер поскольку это будет иметь дело с множественными Exec= линий и % параметров в команде. - Flimm
Спасибо за код - я на Lucid, и я просто сохранил это как /usr/bin/xdg-openpy, и дал ему chmod +x - и использовали launcher.launch([],context) вместо ...None,context) (из-за "TypeError: аргумент 1: должен быть последовательностью, а не NoneType"). Теперь xdg-openpy app.desktop работает из командной строки (и все как обычно при двойном щелчке app.desktop), и он может напомнить мне, если я попытаюсь позвонить в терминал xdg-open и нажмите вкладку. Ура! - sdaau
+1. Это единственный ответ, который не требует ручного разбора .desktop файл, так что это самый разумный (и безопасный) подход. Также использует современные gi.repository вместо устаревших pygtk, так здорово! :) - MestreLion
На самом деле, это вопрос, связанный с ответом Карло Пеллегрини. Я новичок, пожалуйста, поправьте меня, если есть лучший способ разместить его. Скрипт работает очень хорошо, но значок, который я нахожу в Unity launcher, не является значком, определенным в файле .desktop, а значком по умолчанию команды Exec'ed. Есть идеи по этому поводу? - Ingo Leonhardt
@Noitidart напишите последний ответ, который привел mo, чтобы сделать некоторые google, и я нашел что, Не проверял, но, возможно, это помогает - Ingo Leonhardt


Правильный путь

Вы действительно должны использовать gtk-launchесли он доступен. Обычно это часть пакета libgtk-3-Бен (это может варьироваться в зависимости от дистрибутива).

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}}'

Вышеупомянутые команды будут:

  1. Найдите строку, начинающуюся с Exec =
  2. Удалить Exec =
  3. Удалите все переменные Exec (например, %f, %u, %U). Их можно заменить позиционными аргументами, как это предусмотрено спецификацией, но это может значительно усложнить проблему. Смотреть последние Спецификация рабочего стола,
  4. Выполнить команду
  5. Немедленно выйдите с соответствующим кодом выхода (чтобы не выполнять несколько Exec линии)

Обратите внимание, что этот AWK-скрипт обращается к нескольким краевым случаям, которые могут или не могут быть исправлены некоторыми другими ответами. В частности, эта команда удаляет несколько Exec переменные (заботясь о том, чтобы иначе удалить символ%), будет выполнять только один Exec и будет вести себя так, как ожидалось, даже если Exec строка содержит один или несколько знаков равенства (например, script.py --profile=name).

Только несколько других предостережений ... Согласно спецификации, TryExec является:

Путь к исполняемому файлу на диске, который используется для определения того, действительно ли программа установлена. Если путь не является абсолютным путем, файл просматривается в переменной среды $ PATH. Если файл отсутствует или если он не является исполняемым, запись может быть проигнорирована (например, не используется в меню).

Имея это в виду, нет смысла исполнять его ценность.

Некоторые другие проблемы Дорожка а также Терминал, Дорожка состоит из рабочего каталога для запуска программы. Терминал является логическим значением, указывающим, запускается ли программа в окне терминала. Все это можно решить, но нет смысла изобретать колесо, поскольку уже есть реализация спецификации. Если вы хотите реализовать Дорожка, имейте в виду, что system() порождает подпроцесс, поэтому вы не можете изменять рабочий каталог, делая что-то вроде system("cd \047" working_directory "\047"); system(command), Однако вы, вероятно, можете сделать что-то вроде system("cd \047" working_directory "\047 && " command), Примечание \ 047 - одинарные кавычки (поэтому команда не разбивается на пути с пробелами).

Альтернатива Python

Я ворую страницу из Карло Вот, который предложил создать скрипт Python для использования солдат модуль. Вот минимальный способ выполнить один и тот же код из оболочки без необходимости создавать файл и беспокоиться об I / O.

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 не является обязательным. Кроме того, проверка ошибок не выполняется, поэтому вы захотите убедиться, что пусковая установка существует и доступна для чтения (перед ее использованием), если вы хотите, чтобы ваш скрипт был долговечным.


22
2017-08-21 19:33



Но awk команда хорошая. Поэтому +1 - A.B.


Хотя OP не спрашивал о KDE, для тех, кто использует KDE, можно использовать следующую команду:

kioclient exec <path-to-desktop-file>


19
2018-02-23 18:09



Приобретено, потому что оно работает. Не нужно запускать KDE вообще, если у вас установлена ​​эта программа. - basic6
Есть ли способ сделать это? Я скомпилировал clementine player, у которого есть ошибка, которая возникает только при запуске через .desktop-файл (с плазменной оболочкой). И я не могу понять, как иметь выходной журнал журнала anywere. - Kwaadpepper
@Kwaadpepper вы можете использовать ваш файл .desktop для запуска сценария оболочки, который внутренне запускает вашу команду и перенаправляет вывод в файл. - Raman


exo-open [[path-to-a-desktop-file]...]

похоже, работает в версии 13.10, если exo-utils установлен (как в случае с Xubuntu).


10
2017-12-22 15:45



Да, просто протестировали его в Ubuntu Studio 14.04. КСТАТИ. xdg-open и gvfs-open работают тоже. - jarno
Работает также в 15 - Jonathan
Использование Debian с xfce. Прекрасно работает! - king_julien


Вы можете использовать Dex,

dex foo.desktop

10
2018-01-25 23:17



ИМХО - это правильный ответ: один инструмент, один вызов только с параметром. Это то, что я искал, чтобы проверить рукописные .desktop файлы. И он может создавать .desktop файлы тоже, yay! :-) - Axel Beckert
Отлично! Если вы добавите файл .desktop, который использует dex gist.github.com/stuaxo/4169fc1342c496b7c8f7999188f2f242  в / usr / share / applications / вы сможете запускать файлы рабочего стола в файловом менеджере без их открытия в gedit по умолчанию. - Stuart Axon


Добавление к ответу Хэмиша.

Учитывая сценарий deskopen, вы можете использовать ссылку на него как строку shebang в .desktop файл, поскольку символ комментария по-прежнему #, Это означает, что это первая строка .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но он продолжал давать мне «плохую замену» ...


8
2018-02-09 20:12



Я знаю, что это более подходящий комментарий к ответу Хэмиша, но я новый пользователь и не допущен к комментариям. Ну что ж! - pabst
Если у вас есть репутация, самое подходящее действие - это отредактировать этот ответ. - Flimm
Ударьте, что любой может предложить изменения, даже пользователи, которые не вошли в систему! Это ни к чему. - Flimm
Это ответ сам по себе, его штраф. - Bruno Pereira
вы можете использовать "${@:1}" вместо shift, но это требует bash вместо sh в вашей #! притон. ИМХО Ваш первоначальный подход к смене проще и лучше - MestreLion