Getting the current path in .desktop EXEC command

Im trying to make a .desktop file run a .sh which is stored in the same directory as the .desktop. The whole directory needs to be portable and moved from machine to machine.

my run script is run.sh

I’ve tried:

[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;"

But nothing happens when I double click the .desktop file. If I double click ‘run.sh’ and choose ‘run’ the script runs fine. If I run the script from the command line with ‘sh run.sh‘ it works fine.

Any ideas, even just how I could debug which path its actually trying to run from?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

According to the Desktop Entry Specification:

Field codes must not be used inside a quoted argument

Consequently, your %k is given literally to the bash command. Changing the Exec line to the following avoids doing so:

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

The above works locally, and also works if there’s a space in the path. dummy is given to the bash script as its $0 (what it thinks the script name is), and %k‘s expansion is available as $1. The nested layers of quoting are necessary to conform to the specification and be space-safe.

Note that %k doesn’t necessarily expand to a local file path — it can be a vfolder URI, or empty, and a really portable script should account for those cases too. %k also isn’t universally supported itself, so you will need to have some constraints on the systems you expect to use it on anyway.


As far as debugging goes, you can use ordinary shell redirection under KDE:

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

This isn’t standardised behaviour, and it doesn’t work under GNOME and likely others. You can also give an absolute path to a script crafted to log its arguments and actions in the way you need.

Method 2

If the script is in the same directory as the .desktop file, just use relative paths. There’s no reason to fiddle around with bash -c or modifying your $PATH and much less dirname:

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

As long as your run.sh is in the same directory as the .desktop file and has a correct shebang line:
#!/usr/bin/env bash

It should work anywhere. Using #!/usr/bin/env bash instead of #!/bin/bash ensures that whichever bash is in the user’s $PATH will be used and makes your script fully portable.

NOTE: @MichaelHomer pointed out in the comments that relative paths don’t work on all desktop environments. I tried this on Cinnamon and it worked as expected so, presumably, it should also work on other Gnome based environments. The freedesktop.org specifications seem to suggest that a full path should be used:

The Exec key must contain a command line. A command line consists of an executable program optionally followed by one or more arguments. The executable program can either be specified with its full path or with the name of the executable only. If no full path is provided the executable is looked up in the $PATH environment variable used by the desktop environment. The name or path of the executable program may not contain the equal sign (“=”). Arguments are separated by a space.

Method 3

As mentioned in Desktop Entry Specification, %k or other field codes must not be used inside a quoted argument. However, there are ways to copy an expression with space to a variable without using quote:

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

Method 4

A way to run a program (here it is presented a bash script, but it can be adapted for any other program) that has a path relative to the .desktop file parent directory (tested on Gnome, KDE, Xfce, LXDE, LXQt, MATE, Cinnamon, Budgie desktop environments):

Gnome:

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

Gnome – newer:
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'"

An example of .desktop file for the Exec code shown above (except for LXDE and LXQt – for which replace Terminal=false with Terminal=true):
[Desktop Entry]
Version=1.0
Name=Name to display
Comment=A comment
Exec=...
Icon=utilities-terminal
Terminal=false //does not show the initial launcher app (terminal) window
Type=Application
Categories=Application;

For python3, replace bash "./relative_file_path.sh" parameter1 parameterN with python3 "./file_content_search.py" parameter1 parameterN, or – for other programs replace as needed


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments