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 ~
- It is a dry run (
-n
) - The verbosity is at level 2 (
-vv
) - The dotfiles directory is
~/etc/dotfiles
(-d
) - We'll stow the test package that contains a
.test
dotfile - 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.