Получение текущего пути в команде EXEC .desktop

Вопрос или проблема

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

мой скрипт для запуска — run.sh

Я пробовал:

[Desktop Entry]
Type=Application
Terminal=true
Name=RunMe
#Exec=sh -c "`dirname %k`/run.sh"
#Exec=bash -c "export PATH=$PATH:`dirname %k`; bash run.sh;"
#Exec=bash -c "export PATH=$PATH:`dirname %k`; sh run.sh;"
Exec=bash -c "export PATH=$PATH:`dirname %k`; run.sh;"

Но ничего не происходит, когда я дважды щелкаю по файлу .desktop. Если я дважды щелкаю “run.sh” и выбираю “запустить”, скрипт выполняется нормально. Если я запускаю скрипт из командной строки с ‘sh run.sh‘, он работает нормально.

Есть идеи, даже просто как я мог бы отладить, из какого пути он на самом деле пытается запустить?

Согласно спецификациям для Desktop Entry:

Коды полей не должны использоваться внутри кавычек

Следовательно, ваш %k передается буквально команде bash. Изменение строчки Exec следующим образом позволяет избежать этого:

Exec=bash -c '"$(dirname "$1")"/run.sh' dummy %k

Вышеуказанное работает локально, а также работает, если в пути есть пробел. dummy передается скрипту bash как его $0 (что он считает именем скрипта), а расширение кода %k доступно как $1. Вложенные уровни кавычек необходимы для соответствия спецификации и предотвращения проблем с пробелами.

Обратите внимание, что %k не обязательно расширяется до локального пути к файлу — это может быть URI vfolder или пустой, и действительно портативный скрипт должен учитывать и эти случаи. Кроме того, %k также не поддерживается повсеместно, поэтому вам все равно нужно накладывать некоторые ограничения на системы, на которых вы планируете его использовать.


Что касается отладки, вы можете использовать обычное перенаправление shell в KDE:

Exec=bash -c ... > /tmp/desktop.log

Это нестандартизированное поведение, и оно не работает в GNOME и, вероятно, других окружениях. Также можно задать абсолютный путь к скрипту, созданному для ведения журнала его аргументов и действий так, как вам нужно.

Если скрипт находится в той же директории, что и файл .desktop, просто используйте относительные пути. Нет смысла возиться с bash -c или модификацией вашего $PATH, тем более dirname:

[Desktop Entry]
Type=Application
Terminal=true
Name=RunMe
Exec=./run.sh

Пока ваш run.sh находится в той же директории, что и файл .desktop, и имеет корректную строку shebang:

#!/usr/bin/env bash

Он должен работать везде. Использование #!/usr/bin/env bash вместо #!/bin/bash гарантирует использование того bash, который находится в $PATH пользователя, и делает ваш скрипт полностью портативным.


ЗАМЕЧАНИЕ: @MichaelHomer указал в комментариях, что относительные пути не работают во всех окружениях рабочего стола. Я попробовал это в Cinnamon, и это сработало, как и ожидалось, так что, предположительно, это должно работать и в других окружениях, основанных на Gnome. Спецификации freedesktop.org, похоже, предполагают, что следует использовать полный путь:

Ключ Exec должен содержать командную строку. Командная строка состоит из исполняемой программы, за которой опционально следуют один или несколько аргументов. Исполняемая программа может быть указана либо с полным путем, либо только с именем исполняемого файла. Если полный путь не указан, исполняемый файл ищется в переменной окружения $PATH, используемой рабочим столом. Имя или путь исполняемой программы не может содержать знак равенства (“=”). Аргументы разделяются пробелом.

Как упомянуто в спецификации Desktop Entry, %k или другие коды полей не должны использоваться внутри кавычек. Однако есть способы скопировать выражение с пробелом в переменную без использования кавычек:

Exec=k=$(echo %k) && "$(dirname "$k")"/run.sh

Способ запустить программу (здесь представлен скрипт bash, но его можно адаптировать для любой другой программы), путь к которой относительно родительского каталога .desktop файла (проверено на Gnome, KDE, Xfce, LXDE, LXQt, MATE, Cinnamon, Budgie):

Gnome:

Exec=gnome-terminal -e "bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'"

Gnome – новее:

Exec=gnome-terminal -- bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'

KDE:

Exec=konsole -e "bash -c 'cd $(printf '"%s"' "$(dirname "%k")"); bash "./relative_file_path.sh" parameter1 parameterN'"

Xfce:

Exec=xfce4-terminal -e "bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'"

LXDE:

Exec=bash -c 'cd "%k"&&bash "./relative_file_path.sh" parameter1 parameterN'

LXQt:

Exec=bash -c 'cd "%k"&&bash "./relative_file_path.sh" parameter1 parameterN'

MATE:

Exec=mate-terminal -e "bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'"

Cinnamon:

Exec=gnome-terminal -e "bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'"

Budgie:

Exec=tilix -e "bash -c 'cd \"$(dirname "\"%k\"")\"; bash "./relative_file_path.sh" parameter1 parameterN'"

Пример .desktop файла для кода Exec, показанного выше (кроме LXDE и LXQt – для которых замените Terminal=false на Terminal=true):

[Desktop Entry]
Version=1.0
Name=Имя для отображения
Comment=Комментарий
Exec=...
Icon=utilities-terminal
Terminal=false //не отображает начальное окно запуска приложения (терминала)
Type=Application
Categories=Application;

Для python3 замените bash "./relative_file_path.sh" parameter1 parameterN на python3 "./file_content_search.py" parameter1 parameterN, либо – для других программ заменяйте по мере необходимости

Вы можете попробовать более простой и чистый способ:

Exec=`dirname %k`/run.sh

Это работает довольно просто с KDE.

.

Ответ или решение

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

Теория

Первоначально необходимо понять природу .desktop файлов. Эти файлы являются частью спецификации Freedesktop.org и предназначены для упрощения запуска приложений из графической оболочки Linux. В .desktop файле содержится несколько ключей, среди которых ключ Exec определяет команду, которая будет выполнена при запуске файла. Здесь важно учитывать, что расширения и интерпретаторы, такие как Bash или Sh, играют значительную роль при обработке команд.

Одной из частых трудностей является работа с относительными путями в .desktop файле. Несмотря на то, что можно попытаться использовать конструкции с полем %k, эта переменная зачастую не поддерживается полностью на всех рабочих окружениях, и её использование может привести к непредсказуемым результатам или вовсе не сработать.

Пример

Рассмотрим предложенные решения для запуска скрипта из .desktop файла:

[Desktop Entry]
Type=Application
Terminal=true
Name=RunMe
Exec=bash -c '"$(dirname "$1")"/run.sh' dummy %k

Это решение использует конструкцию с переменной %k и предполагает, что Bash интерпретирует выражение для получения директории, в которой расположен .desktop файл. Однако, как отмечалось в документации, этот подход может быть ненадежным, поскольку %k не всегда правильно интерпретируется как локальный путь и может содержать URI или быть пустым.

Альтернативный подход, который часто оказывается более надежным, заключается в использовании относительного пути без сложных команд Bash:

[Desktop Entry]
Type=Application
Terminal=true
Name=RunMe
Exec=./run.sh

Этот подход основывается на том, что скрипт run.sh находится в той же директории, что и сам .desktop файл. Чтобы этот способ работал, необходимо учесть правильное указание shebang в самом скрипте:

#!/usr/bin/env bash

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

Применение

В зависимости от используемой оболочки (например, Gnome, KDE, Xfce и т.д.) либо учитывая специфику среды, могут быть применимы различные варианты команд, обеспечивающих точный переход в директорию .desktop файла и последующий запуск скрипта:

Для Gnome

Exec=gnome-terminal -- bash -c 'cd "$(dirname "%k")"; ./run.sh'

Для KDE

Exec=konsole -e "bash -c 'cd $(dirname "%k"); ./run.sh'"

Для Xfce

Exec=xfce4-terminal -e "bash -c 'cd \"$(dirname '%k')\"; ./run.sh'"

LXDE и LXQt

Exec=bash -c 'cd "$(dirname "%k")" && ./run.sh'

MATE и Cinnamon

Exec=gnome-terminal -- bash -c 'cd "$(dirname \"%k\")"; ./run.sh'

Внимание к структуре команд и учету особенностей каждой среды соответствует требованиям по интеграции скриптов в графические оболочки различных рабочих сред.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...