Запуск файла.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 хранит историю, поэтому легко доступна)

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

xdg-open program_name.desktop

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

На сегодняшний день (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-openhashbang поверх исполняемой записи рабочего стола тоже работает

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

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

kioclient exec <path-to-desktop-file>

На Fedora это включено в kde-runtime оборотов в минуту.

Вы могли бы использовать Dex.

dex foo.desktop

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

Вы действительно должны использовать 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}}'

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

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

(Составлено из различных других ответов здесь)

В зависимости от вашей системы и различных ошибок, которые могут или не могут существовать в вашей системе, попробуйте следующее, пока одна из них не сработает:

  1. xdg-open program_name.desktop
  2. exo-open program_name.desktop
  3. gtk-launch program_name.desktop
  4. kioclient exec program_name.desktop
  5. dex program_name.desktop

Обратите внимание, что в системах Ubuntu ваши пусковые установки рабочего стола "меню пуск" доступны в /usr/share/applications/,

В качестве примера, чтобы показать, какие из перечисленных выше команд работают или не работают в моей системе Ubuntu 14.04, вот результаты следующих вызовов для меня:

  1. xdg-open /usr/share/applications/eclipse_for_cpp.desktop # Сбой из-за ошибки (пытается сохранить этот файл.desktop)
  2. exo-open /usr/share/applications/eclipse_for_cpp.desktop # Работает
  3. gtk-launch /usr/share/applications/eclipse_for_cpp.desktop # Сбой с "gtk-launch: нет такого приложения"
  4. kioclient exec /usr/share/applications/eclipse_for_cpp.desktop # Работает
  5. 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

См. https://gitlab.gnome.org/GNOME/glib/-/issues/54 .

По моему опыту использования приведенных выше ответов, он не дает никакой полезной диагностической информации и немного вводит в заблуждение, сообщая «не найдено» как причину ошибки, а не реальную основную причину. Лучшее, что я смог придумать, это установить 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)
Другие вопросы по тегам