Install a Linux Application Menu Entry with xdg-desktop-menu
You will add a launcher to a Linux desktop application menu, optionally place it in a new submenu, verify the installed files, and remove the entry cleanly when it is no longer wanted. The examples target xdg-utils 1.1.3, installed from Ubuntu package xdg-utils 1.1.3-4.1ubuntu3 on the machine used for this guide.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about 15 minutes. You need a shell, a working application command and permission to write to the chosen installation scope. The user-mode examples do not need sudo. System-wide installation changes what every user sees and normally requires root, so use it only when that is genuinely the intended result.
1. Choose the installation scope
Use an explicit mode in scripts and deployment instructions. user installs for the current user; system installs for all users. Without --mode, the command selects system mode when run by root and user mode for a non-root user. That default can make a command behave differently under automation, so do not leave it implicit.
$ xdg-desktop-menu --version
xdg-desktop-menu 1.1.3
Checkpoint: decide whether this launcher belongs only to your account. For a normal personal launcher, keep using --mode user. Do not add sudo to make an error disappear: it can silently move the installation into the system scope.
2. Create a desktop entry
A desktop entry is an INI-style file whose first section is [Desktop Entry]. Give its filename an alphabetic vendor prefix followed by a dash, such as acme-report.desktop. The prefix prevents name collisions and is checked by the command. A file such as 123-report.desktop fails that check unless you explicitly use --novendor.
[Desktop Entry]
Type=Application
Name=Report Viewer
GenericName=Document viewer
Comment=Open reports from the command line
Exec=/opt/acme/bin/report-viewer %F
Icon=acme-report-viewer
Categories=Office;Viewer;
Type=Application identifies a launcher. Name is the label shown in the menu. Exec is the command to start, and %F allows multiple dropped files. Use %f for one file, or omit a field code if the program does not accept files. Categories lets the desktop place the entry in an existing category-based menu.
Check the command before installing it:
$ test -x /opt/acme/bin/report-viewer
$ printf '%s\n' "$?"
0
If the executable is in your PATH, an unqualified value such as report-viewer %F can be appropriate. An absolute path is easier to audit, but it must exist on every machine receiving the entry.
3. Install one entry in an existing menu
Run this from the directory containing the file:
$ xdg-desktop-menu install --mode user ./acme-report.desktop
$ printf '%s\n' "$?"
0
A successful command is normally quiet and returns status 0. The desktop menu may cache its view, so allow a short delay or reopen the application menu before judging the result. If it does not appear, first inspect the file and the Exec target, then run with a non-zero XDG_UTILS_DEBUG_LEVEL to request more reporting on standard error:
$ XDG_UTILS_DEBUG_LEVEL=1 xdg-desktop-menu install --mode user ./acme-report.desktop
Do not use --novendor as the first fix for a rejected filename. Rename the file with an organisation-owned prefix where possible. The override is useful for controlled, private names, but it removes a collision safeguard.
4. Put entries in a new submenu
To create a submenu, put a .directory file before its desktop entries. The directory file supplies the submenu's title and optional icon:
[Desktop Entry]
Type=Directory
Name=Acme Tools
Comment=Tools supplied by Acme
Icon=acme-tools
Install the directory and both launchers in one call:
$ xdg-desktop-menu install --mode user \
./acme-tools.directory \
./acme-report.desktop \
./acme-cleanup.desktop
The directory file must come first because it identifies the submenu that follows. Multiple directory files can be used to build nested submenus; the entries are added to the last submenu. When the entries are explicitly assigned to a new submenu, Categories is not required for those entries.
For a batch of changes, postpone the menu refresh and perform it once:
$ xdg-desktop-menu install --mode user --noupdate \
./acme-tools.directory ./acme-report.desktop
$ xdg-desktop-menu install --mode user --noupdate \
./acme-tools.directory ./acme-cleanup.desktop
$ xdg-desktop-menu forceupdate --mode user
$ printf '%s\n' "$?"
0
forceupdate is useful after --noupdate. It is not a general repair command, and it does not install missing desktop files or icons.
5. Remove an entry and recover from mistakes
Uninstall the same entry with the same explicit mode:
$ xdg-desktop-menu uninstall --mode user ./acme-report.desktop
$ printf '%s\n' "$?"
0
For a submenu, pass the directory file and the entries that were installed into it:
$ xdg-desktop-menu uninstall --mode user \
./acme-tools.directory \
./acme-report.desktop \
./acme-cleanup.desktop
The submenu and its associated directory file are removed only when no menu entries remain in that submenu. If you removed one entry by mistake, run the original install command again. If the menu still looks stale, use forceupdate after the change.
These commands change menu state. Before using --mode system, record the exact files and command used so another administrator can undo it. A non-zero exit status means the operation failed; the documented values distinguish syntax errors, missing input files, missing required tools, failed actions and unreadable input files. Preserve that status in scripts rather than reporting every failure as a missing launcher.
Done means
- The desktop file has
Type=Application, a workingExecvalue and a vendor-prefixed filename. - The installation uses an explicit
--modematching the intended audience. - A category or directory file places the launcher where you expect it.
- Batch changes use
--noupdatefollowed by oneforceupdate. - The original install command is recorded, and the matching uninstall command is available.