29

The XDG Base Directory Specification provide a set of directory one may used to store data that used to go in so called dot files/directory in the user folder. This post aims to help users who desire use this directories as much as possible.

4 Answers 4

26

Indeed, the current short answer to the question is you can't, as some application hardcode the path. Nevertheless, many application which doesn't specifically support XDG directories enable to set other directories through environment variables. Some time you need to be able to change the system wide configuration, for example with shell, but most of the time, you should be able perform the step as a unprivileged user.

Setting your shell

# Setting bash to use $XDG_CONFIG_HOME/bash, defaults to ~/.config/bash
confdir=${XDG_CONFIG_HOME:-$HOME/.config}/bash

### Moving existing files
mkdir -p -- "$confdir"
for file in "$HOME"/.bash*; do
    dest=$confdir/$(basename "${file:1}") 
    mv -i -- "$file" "$dest" # don't overwrite without permission
done

### Sourcing and setting variables
sudo sh -c 'cat >>/etc/profile.d/bash_in_xdg_config_home.sh <<CONF
# Make bash follow the XDG_CONFIG_HOME convention
_confdir=\${XDG_CONFIG_HOME:-\$HOME/.config}/bash
if [ -d "$_confdir" ] &&  [ "\$0" = "bash" ]
then
    . "\$_confdir"/bash_profile
    . "\$_confdir"/bashrc
    HISTFILE=\$_confdir/bash_history
fi
unset _confdir
CONF
'

sudo sh -c 'cat >>/etc/bash.bash_logout <<CONF
if [ -s "\${XDG_CONFIG_HOME:-\$HOME/.config}/bash/bash_logout" ]
then
    . "\${XDG_CONFIG_HOME:-\$HOME/.config}/bash/bash_logout"
fi
CONF
'

# Setting zsh
## System wide configuration (using xdg directories)
sudo sh -c 'cat >>/etc/zshenv <<CONF
if [[ -d "\${XDG_CONFIG_HOME:-\$HOME/.config}"/zsh ]]
then
        export ZDOTDIR=\${XDG_CONFIG_HOME:-\$HOME/.config}/zsh
fi
CONF
'

If you use several shell, for example zsh for interactive shell, but an other for scripting, you may want to $XDG_CONFIG_HOME/profile file, that you will source in relevant shell initialization script.

Setting environment variables

# bazaar
export BZRPATH=$XDG_CONFIG_HOME/bazaar
export BZR_PLUGIN_PATH=$XDG_DATA_HOME/bazaar
export BZR_HOME=$XDG_CACHE_HOME/bazaar

# gnupg
export GNUPGHOME=${XDG_CONFIG_HOME}/gnupg

# ICEauthority
export ICEAUTHORITY=${XDG_CACHE_HOME}/ICEauthority

#  less
export LESSHISTFILE="${XDG_CONFIG_HOME}/less/history"
export LESSKEY="${XDG_CONFIG_HOME}/less/keys"



# mplayer
export MPLAYER_HOME=$XDG_CONFIG_HOME/mplayer

# subversion
export SUBVERSION_HOME=$XDG_CONFIG_HOME/subversion


# vim
export VIMINIT='let $MYVIMRC="$XDG_CONFIG_HOME/vim/vimrc" | source $MYVIMRC'
export VIMDOTDIR="$XDG_CONFIG_HOME/vim"

Work around

SSH

SSH does provide a way to change the client configuration file, but – as far as I found – only through command line. So one solution to always invoke the clients with a none default emplacement may be :

if [ -s "${XDG_CONFIG_HOME}/ssh/config" ]
then
    SSH_CONFIG="-F ${XDG_CONFIG_HOME}/ssh/config"
fi
if [ -s "${XDG_CONFIG_HOME}/ssh/id_dsa" ]
then
    SSH_ID="-i ${XDG_CONFIG_HOME}/ssh/id_dsa"
fi

alias ssh="ssh $SSH_CONFIG $SSH_ID "
alias ssh-copy-id="ssh-copy-id $SSH_ID"

And your ${XDG_CONFIG_HOME}/ssh/config should contain something like :

Host *
    IdentityFile /home/user/.config/ssh/id_dsa
    UserKnownHostsFile /home/user/.config/ssh/known_hosts

What doesn't work yet

Although GNUPGHOME is a documented variable, under Fedora 21 you'll end up with the creation of a new ~/.gnupg directory when you launch a new session.

Although ICEauthority is a documented variable, under Fedora 21 you'll end up with the creation of a new cookie when you launch a new session.

The dotfile ~/.swt content should probably be stored directly into ${XDG_DATA_HOME}, as both have lib directories. No documentation was found on how to to that if it's possible.

Mozilla products doesn't support an appropriate environment variable, see Mozilla products doesn't allow to use a custom user configuration directory and Support for the Freedesktop.org XDG Base Directory Specification.

Other useful sources

5
  • 1
    When using bash as interactive non-login shell (normal terminal usage), shouldn't /etc/profile be not read at all? Won't our definitions be not set then?
    – Hashken
    Apr 10, 2015 at 10:29
  • 1
    According to the manpage on my system, you are right. Now what I would suggest you is to simply test, as it may depends on your system default configuration. Please give feed back, thank you. May 2, 2015 at 8:54
  • 1
    I can confirm that /etc/profile is not read for non-login shells. But, if you open tmux your /etc/profile is read. This is because tmux opens all its shells as login shells.
    – Hashken
    May 2, 2015 at 9:02
  • 1
    things like history files should be stored under $XDG_CACHE_HOME
    – user187717
    Jul 12, 2015 at 11:46
  • 1) Add: export XAUTHORITY="$XDG_CACHE_HOME/Xauthority" 2) Please quote your variables! (see (1) for an example) 3) For my bash, I needed to: export XDG_CONFIG_HOME=${XDG_CONFIG_HOME:="$HOME/.config"}
    – Tom Hale
    Sep 25, 2016 at 15:18
11

I recommend consulting the Arch Linux wiki page XDG Base Directory support which is continuously updated.

GIT

I just moved my .gitconfig to XDG_CONFIG_HOME on OSX. Per the git-config documentation (link omitted due to reputation).

Second user-specific configuration file. If $XDG_CONFIG_HOME is not set or
empty, $HOME/.config/git/config will be used. Any single-valued variable 
set in this file will be overwritten by whatever is in ~/.gitconfig. It is
a good idea not to create this file if you sometimes use older versions of
Git, as support for this file was added fairly recently.

I set the environment variable using the instructions in Setting the system-wide PATH environment variable in Mavericks. Note that you will need to create the file XDG_CONFIG_HOME/git/config yourself and if ~/.gitconfig exists it will take precedence.

VIM

I used Tom Vincent's 2011 article Vim respect XDG and it seems to work. I'm not sure about the above answer; VIMDOTDIR doesn't seem to be a thing.

2
  • Note: I'm moving to using nixos.org which makes it possible to completely control all configuration in an elegant manner
    – Ben Creasy
    May 8, 2018 at 18:48
  • sourcing vimrc from zsh gives a permission error
    – Saurabh
    Nov 18, 2020 at 23:28
5

Zsh does a slightly better job than bash letting you de-clutter your home using the $ZDOTDIR variable. To move zsh out of the way, you need to add the following to your ~/.zshenv file:

# ~/.zshenv contents
# this is the bare bones setup to move everything to XDG dir
ZDOTDIR=$HOME/.config/zsh

If you have root privledges, you could add this instead to /etc/zsh/zshenv and avoid the need for any zsh dotfiles in your $HOME. From here, all your other zsh dotfiles can be moved to ~/.config/zsh, like .zshrc. I also recommend adding your zsh history to the $XDG_DATA_HOME location: HISTFILE=$XDG_DATA_HOME/zsh/zsh_history.

Some apps will look for the XDG locations by default and you may not even realize it because you still have a legacy dotfile in your $HOME directory. Git is a good example of this - if you have a ~/.gitconfig, try moving it to ~/.config/git/config. My personal favorite, Fish Shell, uses ~/.config by default too.

Also, check your other apps for their own version of a re-$HOME-ing variable. Many support it XDG via a variable:

  • Atom: export ATOM_HOME=$XDG_CONFIG_HOME/atom
  • lpass: export LPASS_HOME=$XDG_CONFIG_HOME/lpass
  • rupa/z has one: export _Z_DATA=$XDG_DATA_HOME/z/z.txt

But there's still quite an extensive XDG wall of shame. Tmux has been actively hostile to supporting de-cluttering your $HOME. Same with pylint. And Julia. And the list goes on. Arch keeps a nice running list of XDG support here.

Honestly, I can't understand the resistance to supporting it. Users need to clearly send a clear message that apps shouldn't be running roughshod over their $HOME. It's not okay anymore. A modern system uses hundreds of apps that pollute $HOME, not tens like it used to be 20 years ago.

3

The most complete resource I’ve found for cleaning up my home directory is xdg-ninja. It’s a tool that inspects the dotfiles and -directories in your home directory and prints a list of solutions for how to configure each individual of software that clutters the home directory. It doesn’t know every single software, of course (and there’s no solution for some!1) but it’s by far the most complete individual list out there, and the tool accepts pull requests for as-yet missing tools.


1 Short of an unmaintained hack via LD_PRELOAD.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .