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

120

Из того, что я могу собрать, .desktop файлов - это ярлыки, которые позволяют настраивать настройки приложения. Например, у меня их много в папке /usr/share/applications/ .

Если я открою эту папку в nautilus , я могу запустить эти приложения, просто дважды щелкнув соответствующий файл, например. двойной щелчок firefox.desktop запускает Firefox. Однако я не могу найти способ сделать то же самое через терминал.

Если я делаю gnome-open foo.desktop , он просто открывает foo.desktop в качестве текстового файла. Если я делаю его исполняемым, а затем запускаю его в bash, он просто терпит неудачу (что ожидается, это явно не скрипт bash).
EDIT: Doing exec /fullpath/foo.desktop дает мне сообщение Permission denied , даже если я перехожу к себе. Если я делаю исполняемый файл и выполняю ту же команду, вкладка терминала, которую я использую, просто закрывается (я предполагаю, что она сработает). Наконец, если я делаю sudo exec /fullpath/foo.desktop , я получаю сообщение об ошибке sudo: exec: command not found .

Это мой вопрос, как я могу запустить файл foo.desktop с терминала?

    
задан Malabarba 04.10.2010 в 13:58
источник

16 ответов

47

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

    
ответ дан Hamish Downer 04.10.2010 в 14:52
источник
64

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

xdg-open program_name.desktop

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

    
ответ дан Richard Holloway 04.10.2010 в 15:28
54

С помощью любого недавнего ubuntu, который поддерживает gtk-launch , просто перейдите

gtk-launch <file> где имя файла .desktop без .desktop part

Итак, gtk-launch foo открывает foo.desktop

Если <file> не находится в /usr/share/application или месте, где вы выполняете gtk-launch , команда gtk-launch <file> <uri> . ( gtk-launch документации )

Используется с терминала или alt + F2 (alt + F2 сохраняет команду в истории так легкодоступной)

    
ответ дан doug 02.12.2013 в 22:32
37

На сегодняшний день (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 something.desktop работает как ожидалось
  • #!/usr/bin/xdg-open hashbang поверх исполняемого рабочего стола тоже работает.

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

    
ответ дан Carlo Pellegrini 11.01.2013 в 09:06
22

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

Вы действительно должны использовать 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 7%s7\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 to an executable file on disk used to determine if the program is actually installed. If the path is not an absolute path, the file is looked up in the $PATH environment variable. If the file is not present or if it is not executable, the entry may be ignored (not be used in menus, for example).

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

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

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

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

    
ответ дан Six 21.08.2015 в 19:33
19

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

kioclient exec <path-to-desktop-file>

    
ответ дан Raman 23.02.2014 в 18:09
10
exo-open [[path-to-a-desktop-file]...]

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

    
ответ дан jarno 22.12.2013 в 15:45
10

Вы можете использовать dex .

dex foo.desktop
    
ответ дан couac 25.01.2015 в 23:17
8

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

Учитывая сценарий 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 ing, но он продолжал давать мне «плохую замену» ...

    
ответ дан pabst 09.02.2012 в 20:12
6

В настоящее время не существует приложения, которое делает то, что вы описываете в архивах 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.

    
ответ дан Emmet Hikory 05.07.2011 в 05:08
6

У меня нет немедленного решения, удовлетворяющего требованиям для ", используя стандартную команду , но если вы хотите минимально разобрать файлы .desktop или хотите создать псевдоним Bash, то должно работать следующее:

  • awk -F= '/Exec=/{system($2); exit}' foo.desktop

другой подход, который может быть интересным, заключается в создании метода binfmt-misc на уровне ядра, чем совпадения в файлах .desktop (см. grep -r . /proc/sys/fs/binfmt_misc/ для тех шаблонов, которые вы в настоящее время разрешили).

В конце дня, что-то , где-то придется разбирать файлы .desktop , это всего лишь вопрос о том, как это делается «стандарт / по умолчанию».

    
ответ дан sladen 09.07.2011 в 21:22
1

При попытке протестировать эти файлы я нашел самый простой способ проверить, что DM или менеджер сеансов будут делать то, что я ожидал, чтобы открыть окружающий каталог в браузере папок пользовательского интерфейса, а затем дважды щелкните, чтобы открыть их.

Если вы находитесь в командной строке: gvfs-open . или gnome-open . откроет ее в браузере настроенных папок.

The sed вещь не будет отражать поведение DM, в том числе необычные вещи, такие как экраны и цитаты, где вы действительно не хотели бы альтернативного поведения. Это не командная строка, но она проверяет все. Я также нашел, что параметр Terminal=true полезен для отладки.

    
ответ дан Danny Staple 19.05.2014 в 15:20
1

Этот SO ответ - это то, что ясно для меня: не пытайтесь выполнить файл рабочего стола, выполните файл, указанный в файле рабочего стола.

Например, выполните /home/jsmith/Desktop/x11vnc.sh

Exec=/home/jsmith/Desktop/x11vnc.sh
    
ответ дан user119824 27.06.2014 в 17:45
1

Я взял сценарий из Карло , и попытался улучшить его для моего собственного использования на рабочем столе.

Эта версия скрипта позволит вам запускать любое приложение, как если бы вы ввели его на 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)
    
ответ дан Fordi 18.09.2015 в 17:20
0

Убедитесь, что сценарий, на который указывает ваш рабочий стол, также является исполняемым.

Если все еще не работает. Сделайте рабочий стол рабочего стола в терминале, изменив Terminal=true и поместив его в скрипт bash. Запустите скрипт, чтобы поймать вывод ошибки. Замените обратно, когда исправлены ошибки.

    
ответ дан hakunami 26.03.2015 в 08:33
0

Ответ Хэмиша велик, но я хотел бы предложить более простую альтернативу, в которой задействовано меньше труб:

$(awk -F= '/^Exec/||/^TryExec/ {print $2;exit}' /usr/share/applications/firefox.desktop)

В этом случае awk ищет строку, начинающуюся с Exec , а затем мы просто печатаем поля после этой строки, используя для цикла и = мы печатаем поле 2, т. е. все, что приходит после этого поля. Кудрявые скобки на концах команд, $(...) , являются подстановкой параметров, поэтому оболочка будет выполнять любые команды awk; в этом случае возвращается фактическая команда, которая появляется после Exec= .

В некоторых редких случаях может быть более одного знака co_de%, что по-прежнему возможно. Для этого я предлагаю

$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)
    
ответ дан Sergiy Kolodyazhnyy 21.08.2015 в 19:55