7

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?

4 Answers 4

7

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.

5
  • thanks, but still nothing happens with: Exec=bash -c '"$(dirname "$1")"/run.sh' dummy %k > log2.log , and nothing is written to the log file at all.
    – Kiksy
    Jul 14, 2014 at 9:33
  • The log file will be in your home directory (if you ran it in KDE). You may have to log standard error too. Absolute paths and xmessage will help debugging. Jul 14, 2014 at 9:42
  • ahh, that was it. Turns out my run.sh was actually pointing in the wrong place, thats working now using your answer. thanks
    – Kiksy
    Jul 14, 2014 at 15:58
  • I am trying to follow same approach to get value to Icon key by: bash -c '"$(pwd)"/image.png' dummy %k But it doesn't work, any reason why? Oct 24, 2014 at 21:50
  • @HarshTrivedi: That sounds like a new question - ask it. You can fit a lot more detail into a question than a comment. Oct 24, 2014 at 21:57
1

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.

1
  • 2
    Relative paths in desktop entries are non-portable - in GNOME this will run the script next to the .desktop, but in KDE it will run from ~. Jul 14, 2014 at 21:33
1

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
1
  • Thanks for the link to the spec.
    – Dan Ortega
    Aug 5, 2021 at 17:29
0

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

2
  • (1) You seem to be saying that the user can’t run bash directly, but has to run it through some sort of terminal command.  And yet the accepted answer doesn’t seem to need to do that. (2) Why do you believe that you need to use pushd instead of cd? Jun 23, 2019 at 3:12
  • You seem to have made two accounts. Please get them merged.
    – muru
    Jun 23, 2019 at 14:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.