Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

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 exectuable 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?

share|improve this question
NB: The reason your exec failed is because exec replaces your currently running process with the process you specify, so what you did was try to replace your shell with running the desktop as a compiled binary. The reason you couldn't sudo exec is because it's a shell builtin and not a binary command. –  Daenyth Oct 4 '10 at 21:11
Interesting, I was wondering why it caused the tab to close. –  Malabarba Oct 4 '10 at 22:41
Related: Hashbang for Gnome .desktop files –  ændrük May 24 '11 at 22:49
I see, they end up parsing the .desktop file. Thank you anyway for the link. –  enzotib May 24 '11 at 22:53
moderators: oops, think I may have flagged this accidentally, sorry if that's the case –  Croad Langshan Feb 28 at 16:30

15 Answers 15

up vote 32 down vote accepted

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/%.//'` &

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

`grep '^Exec' $1 | tail -1 | sed 's/^Exec=//' | sed 's/%.//'` &

Then make it executable

chmod +x ~/bin/deskopen

And then you could do, eg

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

The arguments (%u, %F etc) are detailed at http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.0.html#exec-variables - none of them are relevant for launching at the command line.

share|improve this answer
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 4 '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 4 '10 at 15:20
I've updated my answer with the extra sed - I forgot the desktop files could have arguments. –  Hamish Downer Oct 4 '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 .. –  warl0ck Apr 28 '12 at 6:20
-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 0:36

The answer should be

xdg-open program_name.desktop

But due to a bug this no longer works.

share|improve this answer
On GNOME you can use gnome-open which in turn uses xdg-open which has the bug. –  Richard Holloway Oct 4 '10 at 15:36
WoW this is still a bug, lots of progress in xdg. exo-open is listed as workaround and it opens gedit too. :( –  Drew Oct 17 '11 at 17:59
"no longer works"? It never did! xdg-open works by mimetype association, and .desktop files are associated with text editors, since they are a subclass of text –  MestreLion May 23 '13 at 0:47
this is so stupid (that there is no sensible way to run a Desktop file from the terminal) –  Sam Watkins Jun 21 '14 at 4:23
This bug is still there huh? –  Noitidart Mar 2 at 21:39

As of today (12.10) the bug is still present. It is in fact depending on how gvfs-open (called by xdg-open) works.

Still, I managed 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 :


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__":

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]
Exec=run-desktop %U

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

[Default Applications]


  • xdg-open something.desktop works as expected
  • #!/usr/bin/xdg-open hashbang on top of an executable desktop entry works too

It will be useless work when gvfs-open will solve the bug, but in the meantime...

share|improve this answer
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 9:31
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
+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 0:39
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
@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 5 at 12:36

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

gtk-launch <file> where is the name of the .desktop file without the .desktop part

So gtk-launch foo opens foo.desktop

Usable from terminal or alt+F2 (alt+F2 stores command in history so easily accessible)

share|improve this answer
This is the way, works in debian too. –  nus Feb 13 at 17:51
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 at 16:35

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.

share|improve this answer
Not what I would to hear, anyway thanks for the info –  enzotib Jul 6 '11 at 16:09

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


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:

`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'...

share|improve this answer
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 9 '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 9:33
This is an answer by itself, its fine. –  Bruno Pereira Jan 11 '13 at 9:34
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 1:00

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

share|improve this answer
Thank you, interesting. As "standard" I mean something provided by the DE and conforming to freedesktop.org. –  enzotib Jul 10 '11 at 8:48
Upvote for awk rather than a chain of greps and seds. –  jmtd Oct 21 '13 at 10:57

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>

share|improve this answer
Upvoted because it works. No need to be running KDE at all, as long as you have this program installed. –  basic6 Feb 12 at 19:24
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).

share|improve this answer
Really? Now I get the .desktop file opened in Windows Notepad, rather than the Linux system editor that would have opened it with xdg-open. Not an improvement. –  Auspex Oct 27 '14 at 2:44
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
Works in 15 as well –  Jonathan Leaders May 2 at 18:25

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.

share|improve this answer

You could use dex.

dex foo.desktop
share|improve this answer

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)
share|improve this answer
Nice, awk and Serg =) –  A.B. Aug 21 at 19:56
And sometimes, there is a TryExec, maybe you should check your 2nd command =) –  A.B. Aug 21 at 19:57
@A.B. Hehe, awk is my weapon of choice when it comes to text processing. Besides, it's syntax is close to C. Oh, and already added TryExec part ^_^ –  Serg Aug 21 at 19:59
You have my +1 =) –  A.B. Aug 21 at 20:00
But what's about %f, %u, %U or something like this behind the command? –  A.B. Aug 21 at 20:01

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 $HOME/.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.

    # where you want to install the launcher to

    # the template used to install the launcher

    # ensure $1 has a .desktop extension, exists, is a normal file, is readable, has nonzero size
    # optionally use desktop-file-validate for stricter checking
    # if ! desktop-file-validate "$1" 2>/dev/null; then
    if [[ ! ( $1 = *.desktop && -f $1 && -r $1 && -s $1 ) ]]; then
        echo "ERROR: you have not supplied valid .desktop file" >&2
        exit 1

    # ensure the temporary launcher is deleted upon exit
    trap 'rm "$launcherfile" 2>/dev/null' EXIT

    launcherfile=$(mktemp -p "$appdir" "$template")

    if cp "$1" "$launcherfile" 2>/dev/null; then
        gtk-launch "$launchername" "${@:2}"
        echo "ERROR: failed to copy launcher to applications directory" >&2
        exit 1

    exit 0

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

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 '/^Exec=/ {sub("^Exec=", ""); gsub(" ?%[cDdFfikmNnUuv]", ""); command=$0} END{if (command!="") {exit system(command)} else {if (success!=1) {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"}; 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 original specification intended, but it 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 occur with the commands found in other answers. Specifically, it removes multiple Exec variables (taking care not to otherwise remove the % symbol), will only execute one time, and will behave as expected even if the Exec line command contains an 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 you can't do it with AWK directly as system() spawns a subprocess. You'd want to cd in the shell beforehand.

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

python <<EOF - "$@"
import sys
from gi.repository import Gio

Then execute the launcher function as follows:

launcher LAUNCHER [URI...]
launcher app-name.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.

share|improve this answer
But the awk command is nice. Therefore a +1 –  A.B. Aug 21 at 19:40
Forget it, my mistake :\ –  A.B. Aug 21 at 19:44

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

share|improve this answer

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.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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