how to prevent your home dir from getting littered

keeping your home dir clean and organized with XDG base directory

For most Linux distributions, even in a pristine bare minimum installation, the home directory of a user is already littered with a bunch of files and directories, that contain program configurations, colloquially called dot-files. This gets worse over time, as more programs are installed and used.

benefits of an uncluttered home directory

First of all, the visual clutter of a mass of dot-files and directories is heavily distracting. To get this visual clutter out of your way is big plus.

Second, organizing your data files in respect of data type helps running your backups faster and keeps your backup files smaller. I don’t find it particularly useful for my backups to include stuff like image thumbnails or my web browsers cache. In case of a data loss, such data is automatically reconstructed on the fly (i.e., image thumbnails) or not of much importance (i.e., a web browser’s cache).

theory of operation for an uncluttered home directory

The XDG Base Directory Specification defines a set of locations in a user’s home directory where programs should look for and place user specific files, i.e., configuration files, cache files, state files, runtime files, and application data. These locations are defined by environment variables that start with . All but one of these env vars have a default value, and can be set to user-specific values.

This blog article is rather a walk-through for how get an uncluttered home directory, and keep it uncluttered with the help of the XDG spec. There is an indepth introduction into the XDG Base Directory Specification in the techdoc section of this site.

caveat

The XDG base dirs perfectly suit the mission goal of an uncluttered, clean home directory. Unfortunately, getting an uncluttered, clean home directory in Linux is not a straight forward action. Adoption of the XDG Base Directory Specification by programmers that write tools and programs for *nices, respectively Linux, is pretty low.

In theory, there is no difference between theory and practice. In practice, there is. (Benjamin Brewster, 1882)

how programs decide read/write locations

For programs that follow the XDG base dir spec, the procedure is to read the respective env vars, and, in case the env var is not set or is empty, to use the respective default value defined in the XDG base dir spec. The spec does not define a default value for , which leaves little room for an arbitrary choice ( is a good choice for runtime files).

I always suspected that programs that don’t adhere to the XDG base dir spec just evaluate the env var and dump their stuff right into it. Until the xscreensaver man page told me so:

" ENVIRONMENT
    ....
    HOME      for the directory in which to read the .xscreensaver file. "
xscreensaver man page

configuration for XDG-compliant programs

There are a bunch of programs to configure XDG and read its configuration. I think these programs are an overkill.

Check if you have xdg-user-dirs-update installed on your system. It’s from the suite of XDG helper programs I just mentioned. If installed, it pretty much likely runs during boot up and will mess with your configuration, so it is better to disable it. To disable it, edit and set .

All you need to do is to set the XDG env vars in your . Here is the XDG section of my as an example:

### XDG base dir spec export XDG_CONFIG_HOME=${HOME}/.config export XDG_CACHE_HOME=${HOME}/.cache export XDG_STATE_HOME=${HOME}/.state export XDG_DATA_HOME=${HOME}/files/xdg/data runtime_dir="/idoru/ram/rudolf/runtime" mkdir -p ${runtime_dir} && chmod 0700 ${runtime_dir} && export XDG_RUNTIME_DIR=${runtime_dir} export XDG_DOWNLOAD_DIR=${HOME}/files/download export XDG_DESKTOP_DIR=${HOME}/files/xdg/desktop export XDG_DOCUMENTS_DIR=${HOME}/files/xdg/data export XDG_TEMPLATES_DIR=${HOME}/files/xdg/data export XDG_PUBLICSHARE_DIR=${HOME}/files/xdg/data export XDG_MUSIC_DIR=${HOME}/files/xdg/data export XDG_PICTURES_DIR=${HOME}/files/xdg/data export XDG_VIDEOS_DIR=${HOME}/files/xdg/data

Most of the env vars listed above are self-explanatory, with a few exceptions:

  • XDG_STATE_HOME – actions history (i.e. command history, recently used files) and application state (i.e. view layout, open files)
  • XDG_DATA_HOME – the XDG spec states that this location is for user-specific data files, but doesn’t specify what kind of data. To me, this looks like some kind of kitchen sink directory.

In practice, I have never seen any program on my machine using the following locations: XDG_DOCUMENTS_DIR, XDG_TEMPLATES_DIR, XDG_PUBLICSHARE_DIR, XDG_MUSIC_DIR, XDG_PICTURES_DIR, XDG_VIDEOS_DIR. Not for decades. It might be different on your machine if you are using some heavy-weight desktop environment. But clearly, what’s the point of these directories? I have my templates and documents in directories for the topic, like or . And I do not see any point of having a MP3 collection in my home dir. That’s why I point all these env vars to .

configuration for non-compliant programs

There are three ways to get non-complaint programs to use the XDG base dirs:

  • setting configuration/data locations on the command line – some programs provide arguments to specify where the program reads and writes its configuration and data. Setting an alias for invoking such a program with respective arguments in shell startup files can be a good option.
  • setting env vars – some programs check if specific env vars exist and read/write configuration and data to the respective location. The following section of my below illustrates the point:
    export HISTFILE=${HOME}/.state/bash/bash_history export GIT_CONFIG_GLOBAL=${HOME}/.config/git/gitconfig export GNUPGHOME=${HOME}/.data/gnupg export LESSHISTFILE=${HOME}/.state/lesshst export MPLAYER_HOME=${HOME}/.config/mplayer export WGETRC=${HOME}/.config/wget/wgetrc
  • running the program with – If a program doesn’t provide the respective commandline arguments and doesn’t pick up env vars for configuration/data, but dumps just one kind of data right into , I change the env var to the appropriate XDG dir. I.e., just dumps nothing else but its config right into . With , writes its config where I expect it.

last resort: confine misbehaving programs into a kitchen sink with

Programs that dump all kind of data from config, cache and whatever right into or into a dir right in , can be confined to a kitchen sink directory with . I’m using for it. There are some benefits from this approach:

  • The data doesn’t clutter but is almost completely out of sight.
  • I have a list of programs for which I can check for commandline arguments or environment vars that make the program read/write from/to the appropriate locations.
  • If I do not find such command line arguments or env vars, the program is on the list of programs that I’m on the lookout for replacement.

user specific executables

The XDG spec states that user specific executables are to be located in The notion in the XDG base dir spec that “Distributions should ensure this directory shows up in the UNIX $PATH environment variable, at an appropriate place.”, without the possibility for configuration of the user specific executable dir, is quite patronizing. I’m not a fan of user-specific executables anyway. is good enough for me. So far, I haven’t had .

Java programs

Java programs use the location for user specific configuration (preferences in Java parlance). The default value for is . can be supplied to Java on the command line:

java -Djava.util.prefs.userRoot=${HOME}/.config/java/<app-name> -jar <app JAR-file>

Java programs read on startup the env var and can pick up from . can contain one or more values, whereby the values are separated by . Therefore, the more sane way to export the env var is:

[[ -z ${_JAVA_OPTIONS} ]] && export _JAVA_OPTIONS=<value> || export _JAVA_OPTIONS=${_JAVA_OPTIONS}" <value>"

So, another option is to add the Java config dir to and then start java with the application JAR-file:

[[ -z ${_JAVA_OPTIONS} ]] && export _JAVA_OPTIONS=-Djava.util.prefs.userRoot=${HOME}/.config/java/<app-name> || export _JAVA_OPTIONS=${_JAVA_OPTIONS}" -Djava.util.prefs.userRoot=${HOME}/.config/java/<app-name>" java -jar <app JAR-file>

Putting the above two lines into a shell script has the following advantages:

  • to run the program, you only have to type the obviously much shorter shell script name.
  • only the environment of the shell script is altered. This is important, as other java programs should probably use a different value for .

reference

xscreensaver man page, section Environment

Oracle Java SE 8 Documentation, The JAVA_TOOL_OPTIONS Environment Variable

reddit r/linux Why is compliance with XDG Base Directory Specification so very low?
x