Home News Notes Themes About

GNU Stow

A short GNU Stow tutorial, written mainly as a reminder for myself in the context of setting up my dotfiles.

1. Quickstart

Let's start from a ~/.dotfiles directory. Just run:

stow emacs

This will treat the emacs directory as a Stow package and create a symlink pointing to its content (.emacs.d) in the parent directory, here, the home directory.

~/.emacs.d -> ~/.dotfiles/emacs/.emacs.d

2. Basics

2.1. stow [package]

Some users treat their stow directory as a big, unique package. See an example here. In that case, from ~/.dotfiles, one could run:

stow .

This would stow the current package, creating symlinks to the entire content of ~/.dotfiles in the parent directory (the homedir).

I prefer to have a stow directory with multiple packages in it such as emacs or i3. So in my case, I would simply do:

stow emacs

This stows the emacs package to the parent directory, which is my homedir. This is equivalent to stow --stow emacs, or stow -S emacs.

2.2. stow [package] -t [target]

Now, let's say I am inside one of my packages:

cd emacs

If I want to stow that current package to the home directory, I will run:

stow . -t ~

Here the -t option (target) is used to stow the current package (emacs) to the home directory. Otherwise the target directory would have been the Emacs package's parent directory, ~/.dotfiles.

-t is especially useful if, like mine, your dotfiles directory is not one directory above the home directory. Since I actually use ~/etc/dotfiles, from that directory, I would run:

stow emacs -t ~

2.3. stow -d [directory] [package] -t [target]

If I am not stowing from the dotfiles directory itself, I will run:

stow -d ~/etc/dotfiles emacs -t ~

The -d (directory) option allows you to specify the path of the dotfiles directory if you're not inside it.

2.3.1. A quick observation

Let's quote the manual:

[The -d DIR syntax] also has the effect of making the default target directory be the parent of "DIR"

So if you don't give a -t option, the default target dir will be the parent of the dotfiles directory you specify:

stow -d ~/.dotfiles emacs

This would stow in the home directory (one directory above ~/.dotfiles).

2.4. Dry runs

To test what Stow will do, you can use the -n flag. This will simulate the changes without modifying the file system. To see more than eventual errors, use it in combination with the -v flag.

Here is a moderately elaborate stow command just to summarize everything:

stow -n -vv -d ~/etc/dotfiles test -t ~
  1. It is a dry run (-n)
  2. The verbosity is at level 2 (-vv)
  3. The dotfiles directory is ~/etc/dotfiles (-d)
  4. We'll stow the test package that contains a .test dotfile
  5. We're stowing to the home directory (-t); in other words, we want ~/.test to be a symlink pointing to ~/etc/dotfiles/test/.test

Output:

stow dir is /home/alc/etc/dotfiles
stow dir path relative to target /home/alc is etc/dotfiles
Planning stow of package test...
LINK: .test => etc/dotfiles/test/.test
Planning stow of package test... done
WARNING: in simulation mode so not modifying filesystem.

3. Ignore lists

Files can be excluded from the stowing process using ignore lists.

4. Folding

Let's take a practical example to illustrate what tree folding does.

We want to keep a single file from a VSCode config in the dotfiles directory: ~/.config/Code/User/settings.json. So we create ~/etc/dotfiles/vscode/.config/Code/User/settings.json. What does a dry run tell us?

stow -n -vv -d ~/etc/dotfiles vscode -t ~
stow dir is /home/alc/etc/dotfiles
stow dir path relative to target /home/alc is etc/dotfiles
Planning stow of package vscode...
LINK: .config/Code => ../etc/dotfiles/vscode/.config/Code
Planning stow of package vscode... done
WARNING: in simulation mode so not modifying filesystem.

Yep, this command will create a symlink to ~/etc/dotfiles/vscode/.config/Code/ as ~/.config/Code/. That's tree folding. As the documentation puts it:

This is called tree folding, since an entire subtree is “folded” into a single symlink.

When VSCode is actually started, it will create many other directories and files under ~/.config/Code/. Since it is a symlink, these directories and files will actually be created under ~/etc/dotfiles/vscode/.config/Code/ and pollute version control. That's not what we want.

The solution to this is the --no-folding option:

stow -n -vv -d ~/etc/dotfiles vscode -t ~ --no-folding
stow dir is /home/alc/etc/dotfiles
stow dir path relative to target /home/alc is etc/dotfiles
Planning stow of package vscode...
MKDIR: .config/Code
MKDIR: .config/Code/User
LINK: .config/Code/User/settings.json => ../../../etc/dotfiles/vscode/.config/Code/User/settings.json
Planning stow of package vscode... done
WARNING: in simulation mode so not modifying filesystem.

This time Stow is doing what it can to only create the symlink we are interested in.