241

From what I can gather, .desktop files are shortcuts that allow application's settings to be customized. For instance, I have lots of them in my /usr/share/applications/ folder.

If I open that folder in nautilus, I can run these applications just by double clicking its associated file, e.g. double-clicking firefox.desktop runs Firefox. However, I can't find a way to do the same thing via terminal.

If I do gnome-open foo.desktop it simply opens foo.desktop as a text file. If I make it executable and then run it in bash it simply fails (which is expected, it's clearly not bash script).
EDIT: Doing exec /fullpath/foo.desktop gives me a Permission denied message, even if I change ownership to myself. If I make executable and do the same command, the terminal tab I'm using simply closes (I'm guessing it crashes). Finally, if I do sudo exec /fullpath/foo.desktop, I get an error reporting sudo: exec: command not found.

That's my question, how can I run a foo.desktop file from the terminal?

pl_rock
  • 11,297
Malabarba
  • 10,196

20 Answers20

152

gtk-launch

With any recent Ubuntu that supports gtk-launch just simply go

gtk-launch <file>

Where <file> is the name of the .desktop file with or without the .desktop part. The name must not include the full path.

The .desktop file must be in /usr/share/applications, /usr/local/share/applications or ~/.local/share/applications.

So gtk-launch foo opens /usr/share/applications/foo.desktop (or foo.desktop located in one of the other permitted directories.)

From gtk-launch documentation:

gtk-launch launches an application using the given name. The application is started with proper startup notification on a default display, unless specified otherwise.

gtk-launch takes at least one argument, the name of the application to launch. The name should match application desktop file name, as residing in /usr/share/application, with or without the '.desktop' suffix.

Usable from terminal or Alt + F2 (Alt + F2 stores command in history so it's easily accessible).

crantok
  • 103
  • 3
doug
  • 17,026
  • gtk-launch firefox.desktop ~/.local/share/applications/ launches firefox viewing the directory ~/.local/share/applications/ for me. Seems if you were correct, firefox should not have been passed the directory of the .desktop file as an argument. In fact the directory passed to gtk-launch is not supposed to be used to locate the dir containing the .desktop file (and is not, in fact) – Croad Langshan Feb 28 '15 at 16:35
  • This DOES work for me in Arch Linux also. None of the other answers were satisfactory, but this one is good. :-) It works even though I am running KDE. – MountainX Nov 29 '18 at 19:43
  • 9
    No version of this works for me on Ubuntu 18.10. Everytime it complains the application doesn't exist, whether I'm in the folder with the desktop file or not, whether I include the .desktop extension or not, and whether I separately name the directory or not. – Joseph Garvin Dec 07 '18 at 07:29
  • @ Joseph, I didn't add that part about providing a path, some one else did and probably is wrong. The .desktop needed to be in an applications folder as noted. (/usr/share/applications, /usr/local/share/applications or ~/.local/share/applications – doug Dec 08 '18 at 22:50
  • 1
    well that's utterly pointless. the only real point to would be to launch user-made .desktop launchers. if your app is in /usr/local/share/applications then you can just type the name of the app in the terminal. – tatsu Mar 31 '19 at 17:50
  • 2
    @JosephGarvin Okay I figured it out, it's gtk-launch MYCUSTOMAPP.desktop without the path. works on ubuntu 18.10 – tatsu Mar 31 '19 at 17:54
  • The files could be even in any data dir specified in https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html – jarno Sep 23 '19 at 05:20
  • Thank you for this. I was looking for a way to bypass this issue, while still making use of the .desktop files (for things like %U handling), and gtk-launch worked perfectly. I did download and install the patched version of Nautilus from the MR linked there, but it's great to have a solution that works without downgrading a core system (in terms of GNOME) application. – FallenWarrior Apr 21 '20 at 22:40
  • This doesn't seem to work for files in ~/.local/share/applications/. – geekley Oct 30 '20 at 02:10
  • Ah! kioclient5 exec ~/.local/share/applications/myprogram.desktop worked for me on Kubuntu 20.04. See answer below if you're on KDE. – geekley Oct 30 '20 at 02:54
  • this is a Gnome specific answer, if you DE is not GNOME it will force you to load unneeded libraries to make it work, I strongly suggest to use the @Carlo Pellegrini answer and use glib gio – Lyoneel Jun 22 '23 at 11:05
107

The answer should be

xdg-open program_name.desktop

But due to a bug (here upstream, closed on 2020-12-09) this no longer works.

Pablo Bianchi
  • 15,657
87

Modern Answer

gtk-launch <app-name> - where <app-name> is the file name of the .desktop file, with or without the .desktop extension.

See another answer on this thread for more details. I got this info from that answer.

Deprecated shell tools answer

Written a long time ago - see the comments below this answer as to why this approach won't work for many desktop files.

The command that is run is contained inside the desktop file, preceded by Exec= so you could extract and run that by:

$(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' \
| sed 's/^"//g' | sed 's/" *$//g') &

To break that down

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

You could put this in a file, say ~/bin/deskopen with the contents

#!/bin/sh
$(grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//' \
| sed 's/^"//g' | sed 's/" *$//g') &

Then make it executable

chmod +x ~/bin/deskopen

And then you could do, e.g.

deskopen /usr/share/applications/ubuntu-about.desktop

The arguments (%u, %F etc) are detailed here. None of them are relevant for launching at the command line.

Hamish Downer
  • 19,181
  • This gives the best result so far, but it produces undesirable behavior sometimes. It happens whenever the "Exec=" line has an argument like %u or %i. Bash tries to pass that string as a regular argument. For instance, doing grep '^Exec' firefox.desktop | sed 's/^Exec=//' opens Firefox with a tab that loads www.%u.com. – Malabarba Oct 04 '10 at 15:18
  • For the moment I've added a second sed to remove any arguments. But I think there might be a more "natural" way to run it. – Malabarba Oct 04 '10 at 15:20
  • I've updated my answer with the extra sed - I forgot the desktop files could have arguments. – Hamish Downer Oct 04 '10 at 17:10
  • You should add a "tail -1" to the pipe after "grep" , since "Exec=" can be appear multiple time , and after that , only the last appearance should be executed .. – daisy Apr 28 '12 at 06:20
  • @warl0ck: thanks for that - I've updated the answer with your suggestion. – Hamish Downer May 02 '12 at 08:36
  • 15
    -1: This may work for simple .desktop files, but it ignores entries like Path= and TryExec= which may affect execution. It also executes the wrong Exec= if the file contains Desktop Actions ("quicklists") – MestreLion May 23 '13 at 00:36
  • It doesn't show the icon of the application. Is this an expected behaviour or I should have something wrong in some file? – Lucio May 28 '13 at 20:26
  • This didn't worked for me. It seems any paths are double quoted. The script by Carlo worked. – Albert Jun 21 '13 at 11:08
  • This gave me problems with vlc.desktop, it had an option in the form of --started-from-file. I added another pipe to strip that: sed 's/-.*//g'... I barely know how to use sed, so I don't know if this is without problems. – Samuel Feb 21 '17 at 04:51
  • hackish hack is hacky - need solution that causes the desktop to run it – nhed May 18 '18 at 15:11
  • This answer fails when the exec string ended in a double quote mark. It removed the last one but left the first one. For example: Exec=su-to-root -c "/usr/local/bin/ddm-mx -i nvidia" resulted in: su-to-root -c "/usr/local/bin/ddm-mx -i nvidia. – Bob C Sep 07 '19 at 13:00
  • @BobC yep, just change the two last seds to: sed 's/^"\(.*\)"$/\1/g' – knezi Aug 22 '20 at 17:13
  • I like your "Deprecated shell tools answer", which, albeit imperfect for all cases, works for most desktop files. So, I've upvoted your answer and put that script into my own summary answer too. – Gabriel Staples Mar 13 '21 at 03:51
  • For those who found that answer by googling and wanted to start desktop file, for gtk-launch the file has to be located in certain folders, see https://unix.stackexchange.com/questions/393079/gtk-launch-only-works-when-present-working-directory-is-desktop – Alex Martian Sep 11 '21 at 05:30
66

Since glib 2.67.2 there's a gio launch command that can be used like this:

gio launch ./foo.desktop

For older releases I've got a quick workaround (stealing inspiration from the nautilus source code). It is a bit convoluted, but works flawlessly on Ubuntu 12.10, adding a meaningful icon (no more ?) on the Unity launcher.

First, I wrote a python script using Gio and placed saved it as ~/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)

The script needs to have the executable permission, so I ran this in a terminal:

chmod +x ~/bin/run-desktop

Then I created the relative .desktop entry on ~/.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

Finally, I associated the entry as the default handler in ~/.local/share/applications/mimeapps.list under the [Default Applications] section as :

[Default Applications]
....
application/x-desktop=run-desktop.desktop

Now:

  • xdg-open something.desktop works as expected
  • #!/usr/bin/xdg-open hashbang on top of an executable desktop entry works too
Hi-Angel
  • 3,702
  • 1
  • 29
  • 36
  • 1
    This works better than Hamish Downer's answer as it will deal with multiple Exec= lines and % parameters in the command correctly. – Flimm Jan 11 '13 at 09:31
  • 4
    Thanks for the code - I'm on Lucid, and I simply saved this as /usr/bin/xdg-openpy, and gave it a chmod +x - and used launcher.launch([],context) instead of ...None,context) (because of "TypeError: argument 1: Must be sequence, not NoneType"). Now xdg-openpy app.desktop works from command line (and all as normal when double-clicking app.desktop), and it can remind me if I try to call in terminal xdg-open and press tab. Cheers! – sdaau Feb 12 '13 at 19:40
  • 5
    +1. This is the only answer that does not require manually parsing the .desktop file, so it's the most sane (and safe) approach. Also uses modern gi.repository instead of the deprecated pygtk, so great! :) – MestreLion May 23 '13 at 00:39
  • 2
    In fact, this is a question concerning Carlo Pellegrini's answer. I'm a newby, please correct me if there was a better way to place it. The script works really fine, but the icon I get on the Unity launcher is not the icon defined in the .desktop file but the the default icon of the 'Exec'ed command. Any ideas about that? – Ingo Leonhardt May 24 '13 at 14:23
  • @IngoLeonhardt did you ever find a fix to that? I'm also trying to get the icon to be that of the .desktop file. – Noitidart Mar 03 '15 at 06:38
  • @noitidart unfortunately not, I've learned to live with it and haven't made any more efforts – Ingo Leonhardt Mar 03 '15 at 11:25
  • Thanks @IngoLeonhardt for the reply! I'm actually finding lots of documentation on Gio and it has a lot of stuff mentioning icon (such as gdk_app_launch_context_set_icon_name) I think this is very possible! Did you explore the Gio docs? I'm reading code here: https://github.com/mathitme/nautilus/blob/2944be953ef54717bb24968b0eebe468c9705db4/libnautilus-private/nautilus-program-choosing.c#L142 – Noitidart Mar 03 '15 at 15:46
  • @noitidart my concern was starting things like specially parametrized xterms with a different icons to be able to distinguish one form another. So I haven't looked at C code. Nevertheless if you find something I would be glad if you let me know – Ingo Leonhardt Mar 03 '15 at 16:40
  • Will definitely keep you updated @IngoLeonhardt :) I badly need the custom icon solution :) – Noitidart Mar 03 '15 at 17:42
  • Hey @IngoLeonhardt I figured out the c code to do this and it does launch with the custom icon! This is firefox js-ctypes code. To run it you can follow this youtube vid: https://www.youtube.com/watch?v=Rzgf7-I5QPg are you sure the icon of the .desktop file was not used? – Noitidart Mar 03 '15 at 22:22
  • @IngoLeonhardt I tested launching .desktop file on Ubuntu 14.04 and it launched and the custom icon of the .desktop took everywhere. But on Mint Cinnamon 17.1 the .desktop file if double clicked or if launched with Gio it doesn't take the icon of the .desktop. I'm thinking of looking into using gdk_app_launch_context_set_icon_name with Gio launch_uris, maybe it will make it take the icon, any idea? – Noitidart Mar 04 '15 at 21:47
  • @Noitidart not at the moment (and not too much time either). But I've updated my run-desktop to the current version of this answer and still gnome-terminal is launched with it's default icon, not the one form the .desktop (Ubuntu 14.04 too) – Ingo Leonhardt Mar 05 '15 at 12:30
  • 1
    @Noitidart write the last answer led mo to do some google and I found that. Haven't checked it out, but maybe it helps – Ingo Leonhardt Mar 05 '15 at 12:36
  • xseticon looks interesting it must be a custom function which sets _NET_WM_ICON – Noitidart Mar 05 '15 at 15:34
  • @IngoLeonhardt yep XChangeProperty is how they do it i downloaded that file: https://gist.github.com/Noitidart/64ad2edbda32627b684f – Noitidart Mar 05 '15 at 15:41
63

While OP was not asking about KDE, for anyone that is running KDE the following command can be used:

kioclient exec <path-to-desktop-file>

On Fedora, this is included in the kde-runtime rpm. On Arch, it is in kde-cli-tools (HT: @Aron Cederholm).

Raman
  • 741
  • 9
    Upvoted because it works. No need to be running KDE at all, as long as you have this program installed. – basic6 Feb 12 '15 at 19:24
  • Is there a way to have stdout of this ? I have compiled clementine player, which has a bug that occurs only launching through .desktop file (with plasma-shell). And i can't figure out, how to have output log log anywere. – Kwaadpepper Nov 16 '15 at 14:22
  • @Kwaadpepper you could use your .desktop file to launch a shell script, which internally runs your command and redirects output to a file. – Raman Nov 18 '15 at 08:03
  • I do not find kioclient in any package of KDE for Arch Linux at this time. However, gtk-launch works under KDE for me. – MountainX Nov 29 '18 at 19:49
  • 3
    kioclient5 exec ~/.local/share/applications/myprogram.desktop worked for me on Kubuntu 20.04 – geekley Oct 30 '20 at 02:52
  • @geekley It worked in KDE Neon 5.22.4 (Ubuntu 20.04) as well. – RatajS Aug 30 '21 at 10:22
  • @MountainX, it is located in package kde-cli-tools – Xyz Apr 08 '22 at 08:03
43

You could use dex: generate and execute Application type .desktop files.

DesktopEntry eXecution implements the Freedesktop.org autostart specification, independent of any desktop or window manager environment.
Applications may be filtered based on the Desktop Environment advertised in the .desktop file.

Install dex:

sudo apt install dex

Run the file with it:

dex foo.desktop
Pablo Bianchi
  • 15,657
couac
  • 431
  • 4
  • 2
  • 4
    IMHO this is exactly the right answer: One tool, a single call with only the file as parameter. That's what I was looking for, too, to test hand-written .desktop files. And it can create .desktop files, too, yay! :-) – Axel Beckert Jul 31 '16 at 15:42
  • 1
    Perfect! If you add a .desktop file that uses dex https://gist.github.com/stuaxo/4169fc1342c496b7c8f7999188f2f242 to /usr/share/applications/ you will be able to launch desktop files in the filemanager without them opening in gedit by default too. – Stuart Axon Dec 19 '16 at 11:47
  • $ dex chromium.desktop yields: File does not exist: /home/$USER/chromium.desktop. This solution isn't very portable, you're otherwise forced to use $ dex /usr/share/applications/chromium.desktop. gtk-launch works without the full path. – thiagowfx Aug 02 '21 at 16:49
42

The Right Way

You should really be using gtk-launch if it is available. It is usually part of the package libgtk-3-bin (this may vary by distro).

gtk-launch is used as follows:

gtk-launch APPLICATION [URI...]
gtk-launch app-name.desktop
gtk-launch app-name

Please note that gtk-launch requires the .desktop file to be installed (i.e. located in /usr/share/applications or ~/.local/share/applications).

So to get around this, we can use a hackish little Bash function that temporarily installs the desired .desktop file before launching it. The "correct" way to install a .desktop file is via desktop-file-install but I'm going to ignore that.

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

    )

}

You can use it like so (and also pass along additional arguments or URIs if you want):

launch PATH [URI...]
launch ./path/to/shortcut.desktop

The Manual Alternative

If you want to manually parse and execute a .desktop file, you can do so with the following awk command:

awk '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); exit system($0)}' app-name.desktop

If you want to treat the awk command like an all-in-one script; we can even show an error message and exit with a return code of 1 in the event that an Exec command is not found:

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 \047%s\047\n", FILENAME > "/dev/stderr"} close("/dev/stderr"); exit 1}}'

The aforementioned commands will:

  1. Find the line starting with Exec=
  2. Remove Exec=
  3. Remove any Exec variables (e.g. %f, %u, %U). It is possible to replace these with positional arguments as the specification intends, but doing so would add significant complexity to the problem. See latest Desktop Entry Specification.
  4. Execute the command
  5. Immediately exit with the appropriate exit code (so as to not execute multiple Exec lines)

Note, this AWK script addresses a few edge cases that may or may not be properly addressed by some of the other answers. Specifically, this command removes multiple Exec variables (taking care not to otherwise remove the % symbol), will only execute a single Exec line command, and will behave as expected even if the Exec line command contains one or more equals sign (e.g. script.py --profile=name).

Just a few other caveats... According to the specification, TryExec is:

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).

With that in mind, it doesn't make sense to execute it's value.

Some other concerns are Path and Terminal. Path consists of the working directory to run the program in. Terminal is a boolean that indicates whether the program is run in a terminal window. These can all be addressed, but there's no sense in reinventing the wheel as there are already implementations of the spec. If you do want to implement Path, keep in mind that system() spawns a subprocess, so you can't change working directory by doing something like system("cd \047" working_directory "\047"); system(command). However you could presumably do something like system("cd \047" working_directory "\047 && " command). Note \047 are single quotes (so the command doesn't break on paths with spaces).

The Python Alternative

I'm stealing a page from Carlo here, who suggested creating a Python script to make use of the gi module. Here's a minimal way to execute the same code from the shell without having to create a file and worry about 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

}

Then execute the launcher function as follows:

launch ./path/to/shortcut.desktop

Note the use of URIs is optional. Also, no error checking is performed so you'll want to ensure the launcher exists and is readable (before using it) if you want your script to be durable.

Six
  • 832
  • 7
  • 7
  • But the awk command is nice. Therefore a +1 – A.B. Aug 21 '15 at 19:40
  • What is a URI in this context? I have a desktop file in an arbitrary folder. How the heck do I just run gtk-launch on it without having to wrap it in some other script? This is maddening. – Joseph Garvin Dec 07 '18 at 07:30
  • This awk solution will not properly work if the command has double-escaped whitespaces or backslashes. It breaks on this: Exec=env WINEPREFIX="/path/to/.wine" wine c:\\\\windows\\\\command\\\\start.exe /Unix /path/to/.wine/dosdevices/c:/users/Public/Рабочий\\ стол/appname.lnk And dex solution works fine. – MarSoft Mar 08 '19 at 17:15
  • I like the Python solution. No messing about with string operations, thus avoiding some shell argument pitfalls. – Radu C Aug 27 '23 at 18:14
21
exo-open [[path-to-a-desktop-file]...]

seems to work in 13.10 release, if exo-utils is installed (like is the case with Xubuntu).

jarno
  • 5,600
  • Yes, just tested it in Ubuntu Studio 14.04. BTW. xdg-open and gvfs-open work there, too. – jarno Oct 28 '14 at 16:53
15

(Compiled from the various other answers here)

Depending on your system, and the various bugs that may or may not exist on your system, try the following until one of them works:

  1. xdg-open program_name.desktop

  2. exo-open program_name.desktop [my preferred choice, whenever it works]

  3. gtk-launch program_name.desktop

  4. kioclient exec program_name.desktop

  5. dex program_name.desktop

  6. gio launch program_name.desktop

    See @Carlo Pellegrini's answer here.
    See the help menu with gio -h, and the manual pages with man gio.

  7. Or, here's a command from @Hamish Downer which grep-searches the *.desktop file for the Exec= line containing the command to execute, removes parts of that line we don't want, then executes it. It is well-written and works well for most desktop files. See his answer for a full explanation of it.

    # To execute the `Exec=` cmd from filename.desktop in the background
    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//' \
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') &
    

    Or, remove the &amp; at the end to execute it in the foreground so you

    can see output from running the command too

    $(grep '^Exec' filename.desktop | tail -1 | sed 's/^Exec=//'
    | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g')

Note that on Ubuntu systems, your "start menu" desktop launchers are available in /usr/share/applications/.

As an example, to show which of the above commands do or don't work on my Ubuntu 14.04 system, here are the results of the following calls for me:

  1. xdg-open /usr/share/applications/eclipse_for_cpp.desktop # Fails due to bug (tries to have me save this .desktop file)
  2. exo-open /usr/share/applications/eclipse_for_cpp.desktop # Works
  3. gtk-launch /usr/share/applications/eclipse_for_cpp.desktop # Fails with "gtk-launch: no such application"
  4. kioclient exec /usr/share/applications/eclipse_for_cpp.desktop # Works
  5. dex /usr/share/applications/eclipse_for_cpp.desktop # Fails, & sudo apt install dex cannot locate package dex
  6. $(grep '^Exec' /usr/share/applications/eclipse_for_cpp.desktop | tail -1 | sed 's/^Exec=//' | sed 's/%.//' | sed 's/^"//g' | sed 's/" *$//g') & # Works
  • 1
    To make this complete, you should add gio launch <path to .desktop file> which supports using a custom .desktop file at any location (https://askubuntu.com/a/239883/916841). – ChrisN Feb 29 '24 at 08:29
  • @ChrisN, good addition. Thank you. I added it to the answer. – Gabriel Staples Feb 29 '24 at 17:51
10

Addendum to Hamish's answer.

Given the deskopen script, you can use a reference to it as the shebang line in a .desktop file, since the comment character is still #. That is to say, put this as the first line of the .desktop file:

#!/usr/bin/env deskopen

Then flag the .desktop file as executable (e.g. with a chmod +x whatever.desktop), and then you can

path/to/whatever.desktop

and voilà -- The app will open! (Complete with the icon file I specified, though I have no idea how.)

Now, if you also want deskopen to pass through any command-line parameters, you can instead use this slightly-modified version:

#!/bin/sh
desktop_file=$1
shift
`grep '^Exec' "${desktop_file}" | sed 's/^Exec=//' | sed 's/%.//'` "$@" &

As an aside, I tried using "#{@:2}" instead of shifting, but it kept giving me 'bad substitution'...

pabst
  • 101
  • I know this is more appropriately a comment to Hamish's answer, but I'm a new user and not allowed to comment. Oh well! – pabst Feb 09 '12 at 20:14
  • If you have the reputation, the most appropriate action would be to edit that answer, actually. – Flimm Sep 13 '12 at 12:58
  • Strike that, anyone can suggest edits, even users who haven't logged in! It's no biggie any way. – Flimm Jan 11 '13 at 09:33
  • you can use "${@:1}" instead of shift, but that requires bash instead of sh in your #! shebang. IMHO your original shift approach is simpler and better – MestreLion May 23 '13 at 01:00
  • I did as you said I created the shell. and in my desktop file i added the shebang at top. But its not opening with the icon i set on the .desktop file :( I can share a screencast of my situation if you are available :) – Noitidart Mar 03 '15 at 06:58
8

I don't have an immediate solution meeting the requirement for "using a standard command", but if you did want to minimally parse the .desktop files or wanted to create a Bash alias, then the following should work:

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

another approach that might be interesting, would be to create a kernel-level binfmt-misc method than matches on .desktop files (see grep -r . /proc/sys/fs/binfmt_misc/ for those patterns that you currently have enabled).

At the end of the day, something somewhere will have to parse the .desktop files, it's just a question of how "standard/default" that is.

sladen
  • 6,424
6

There isn't currently an application that does what you describe in the Ubuntu archives. There are a couple efforts in progress to create a general solution to provide integration for desktop environments (like openbox) that are not compliant with these XDG specifications.

Arch Linux is working on an implementation of xdg-autostart based on the python-xdg libraries. From what I can find, this seems not yet entirely complete, but has some reports of success.

There is also a C++ implementation of xdg-autostart on gitorious (http://gitorious.org/xdg-autostart/) which would likely benefit from wider use.

If either solution works for you, please consider submitting the necessary work for inclusion in either Debian or Ubuntu.

To use either tool with openstart, you would call it in /etc/xdg/openbox/autostart.sh (if I am reading the openbox documentation correctly). If this doesn't work, you can probably call it in any of the openbox session initialisation scripts.

Emmet Hikory
  • 4,075
2

This SO answer is what made it clear for me: don't try to execute the desktop file, execute the file pointed to in the desktop file.

For example, execute /home/jsmith/Desktop/x11vnc.sh

Exec=/home/jsmith/Desktop/x11vnc.sh
user119824
  • 21
  • 1
2

Hamish's answer is great, but I'd like suggest a simpler alternative, with less piping involved:

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

In this case, awk searches for line starting with Exec, and then we simply print fields after that line, using for loop and = we print field 2, i.e., whatever comes after that field. The curly brackets on the ends of the commands, $(...), are parameter substitution, thus shell will execute whatever awk command returns; in this case, it returns actual command that comes after Exec=.

In some rare cases there may be more than one = sign, which is still a possibility. For that, I suggest

$(awk -F= '/^Exec/||/^TryExec/ {for(i=2;i<=NF;i++) print $i;exit}' /usr/share/applications/firefox.desktop)
A.B.
  • 90,397
Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
2

I took the script from Carlo's answer above, and made an attempt to improve on it for my own desktop use.

This version of the script will allow you to run any app as if you entered it on the HUD, so long as it's likely to be the first result. It also lets you pass file arguments for .desktop files that do not support URIs.

#!/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)
David Foerster
  • 36,264
  • 56
  • 94
  • 147
Fordi
  • 299
1

In my experience with trying the above answers, gtk-launch does not provide any helpful diagnostic information, and is slightly misleading, reporting "not found" as the cause of the error rather than the real root cause. The best I could come up with was installing rofi with sudo apt install rofi and then launching it from the terminal with:

rofi -show drun

Then, I selected my application using its fuzzy-finder, and after pressing enter, it actually gave me the real reason for why the *.desktop file would not launch (in my case, I had quotes around the Exec-line in my *.desktop file).

Does anybody know where the source-code is for gtk-launch? This really seems like we should create a PR for giving better, more accurate error messages, as this seems to be a prevalent problem when searching around the net.

Edit1: I found the gtk-launch source here

1
cd /usr/share/applications
gio launch program_name.desktop

See https://gitlab.gnome.org/GNOME/glib/-/issues/54

karel
  • 114,770
cass
  • 11
1

When trying to test these files I found the simplest way to check that that the DM or session manager would do what I expected was to open the surrounding dir in a UI folder browser and then double-click to open them.

If you are in a command line : gvfs-open . or gnome-open . will open it in the configured folder browser.

The sed thing will not mirror the DM's behaviour, including fiddly stuff like escapes and quoting where you really wouldn't want alternative behaviour. It's not command line, but it did validate things. I also found setting Terminal=true useful for debugging.

  • The terminal disappears immediately, I don't have the time to see the message when using Terminal=true :s – gouessej Oct 29 '15 at 11:53
1

Make sure the script your desktop file points to is executable too.

If still doesn't work. Make desktop file runnable in terminal by changing Terminal=true, and put it inside a bash script. Run the script to catch the error output. Change back when errors are corrected.

hakunami
  • 655
-1

"I am using Ubuntu 20.10 (Groovy Gorilla)"

Just open the terminal and then navigate to that folder where .desktop file is located and then type

chmod +x (name of desktop file)
./(name of desktop file)
Zanna
  • 70,465