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