Hand a file or URL to xdg-open and it just works, using whatever application the desktop already prefers. This covers a reliable invocation pattern plus a small shell trick for catching failures. It uses the xdg-open supplied by xdg-utils 1.1.3-4.1ubuntu3 on the machine checked for this guide; the man page names the upstream project xdg-utils 1.0, so the installed command is treated as the authority here.
Allow about ten minutes. You need a graphical desktop session, a shell, and an existing file that your account can read. The command is normally unprivileged: it opens something in another application but does not itself configure the default application or edit the file.
Check which executable your shell will run and record the installed version:
$ command -v xdg-open
/usr/bin/xdg-open
$ xdg-open --version
xdg-open 1.1.3
The version string on your machine may differ. The only supported invocations are one file or URL, or one of --help, --manual and --version. xdg-open expects a desktop session: a server reached over SSH, a text-only virtual console, or a scheduled job may have no display or application to hand the request to.
Warning: do not run it with sudo as a shortcut. The manual specifically advises against xdg-open as root. Root can have different desktop settings, and a graphical application launched as root can leave root-owned configuration or data in a user's environment.
Pass one supported URL as the sole argument, quoted so shell metacharacters, spaces or query-string characters cannot change how it gets parsed:
$ xdg-open 'https://example.com/documentation'
There is usually no useful text to capture: the expected result is that the desktop's preferred browser opens the URL. A zero exit status means the action was accepted as successful:
$ xdg-open 'https://example.com/documentation'
$ printf '%s\n' "$?"
0
The schemes this installed command documents are file, ftp, http and https. Do not pass a URL from an untrusted source without thinking about where it opens: xdg-open delegates to another application, and that application still processes the content.
Give an existing path and let the desktop's MIME association pick the application. This example uses a placeholder path you must replace:
$ xdg-open '/home/you/Documents/notes.pdf'
$ printf '%s\n' "$?"
0
A successful return means xdg-open considers the action a success. It does not prove the viewer finished loading the file, or that the document was safe, complete or visually correct. Keep the source file in place until the receiving application has actually opened it.
Check a path before passing it when it comes from a script or a copied command:
file='/home/you/Documents/notes.pdf'
if [ ! -f "$file" ]; then
printf 'Missing regular file: %s\n' "$file" >&2
exit 1
fi
xdg-open "$file"
status=$?
printf 'xdg-open status: %s\n' "$status" >&2
exit "$status"
Always quote the variable. Without quotes, a path containing spaces splits into several arguments and xdg-open rejects the extras.
Use the status rather than parsing output. The documented failure codes are:
1: command-line syntax was invalid, such as no argument or more than one.2: a file named on the command line did not exist.3: a required tool or handler could not be found.4: the requested action failed.This case statement keeps a typo in a path distinct from an unavailable desktop handler:
xdg-open "$1"
status=$?
case "$status" in
0) printf '%s\n' 'Opened successfully' ;;
1) printf '%s\n' 'Usage error: give exactly one file or URL' >&2 ;;
2) printf '%s\n' 'The file does not exist' >&2 ;;
3) printf '%s\n' 'No suitable handler was found' >&2 ;;
4) printf '%s\n' 'The desktop action failed' >&2 ;;
*) printf 'Unexpected xdg-open status: %s\n' "$status" >&2 ;;
esac
exit "$status"
This script expects one argument. If you save it as a wrapper, validate the argument count before touching $1 so an empty invocation does not produce a confusing secondary error.
& starts a background shell job, and spaces split a path into multiple arguments. Single quotes are a good default for literal values; a value containing a single quote needs a carefully quoted shell variable instead of guesswork.cron, systemd or an SSH session, where the variables and desktop services differ.Start with the read-only checks below:
$ printf 'DISPLAY=%s\nWAYLAND_DISPLAY=%s\nXDG_CURRENT_DESKTOP=%s\n' "$DISPLAY" "$WAYLAND_DISPLAY" "$XDG_CURRENT_DESKTOP"
$ xdg-open --help
$ ls -l '/home/you/Documents/notes.pdf'
An empty display-related environment does not prove there is no graphical session, but it is a useful clue when a remote or scheduled invocation fails. Check the file's spelling and permissions before changing anything. If status 3 appears, inspect which desktop application handles the file type or URL scheme using your desktop's own settings; installing or changing an association is a separate, deliberate job.
Recovery: there is no undo command in xdg-open, because it does not change the underlying content. Closing the application it opened is the appropriate recovery for an unwanted launch. If that application edits a file, use its own save, close or version-history controls.