Using GNU Stow
2013-12-01
stow
is a cool little Perl script which basically just creates and deletes
symlinks. That sounds pointless, but let me explain with an example. Let's say
you want to install a program using the usual make install
, which probably
installs into /usr/local, which means it's separated from the rest of your
system, which is managed with a "real" package manager. Unless you're using a
system like BSD ports or Gentoo portage, you cannot have packages which are both
managed by the package manager and customised according to your needs. In
fact, if you need to do any in-depth modification of the source, I'd say you
have no other option than using make
, meaning you have a whole mess of files
under /usr/local. This wouldn't be a problem with package managers, since this
"mess" of files can be removed by uninstalling the package, which usually has a
list of files it installed, ensuring all stray man pages and example configs are
purged from your filesystem. If you used make install
, and there is no make
deinstall
or similar, then you're out of luck. The only way to remove the
programs you just installed is to wade through the mess that is /usr/local and
remove the files manually. That's where stow
comes in.
The idea of stow
is that you compile your programs normally using make
, but
install it into a different directory, usually something like
/usr/local/stow/$PKGNAME. This means there is an entire directory tree in that
directory containing all of the files that would have been installed by that
Makefile. You then enter the /usr/local/stow directory and use the command stow
$PKGNAME
, which creates appropriate symlinks in the directory /usr/local to
make it seem as if you just installed the package with make install
into
/usr/local. At first, this seems completely useless, but it means you have a
guaranteed way of deleting that package - tell stow
to delete all the
symlinks. You do this by going into /usr/local/stow and typing stow -D
$PKGNAME
, which removes all of the symlinks in /usr/local. Here is a series of
commands someone using stow
might execute.
$ sudo mkdir /usr/local/stow/my_program
$ cd /tmp/my_program
$ make install DESTDIR=/usr/local/stow/my_program
$ cd /usr/local/stow
$ stow my_program
This makes it very simple to upgrade packages or keep multiple concurrent versions lying around.
Using Stow for dotfile management
Admittedly, stow
is not really that useful on a bog standard GNU/Linux desktop
or laptop, since most packages would be compiled with the usual combinations of
compile-time features enabled and available in package repos. The behaviour of
stow
can be exploited to provide some other uses, however, one of which
involves dotfiles.
Let's say a user named bob wants to check his dotfiles into his favourite version control system and deploy them easily and quickly on other computers. Right now he has a home directory which looks like this:
bob
|-- .bash_profile
|-- .bashrc
|-- .config
|-- .mutt
| |-- config_1
| |-- config_2
| `-- config_3
|-- .vim
| |-- bundle
| `-- ftplugin
`-- .vimrc
Since stow
works by recreating a tree of symlinks in the directory above where
it is invoked, bob can make a directory called "~/dotfiles" or similar, put all
of his dotfiles in there, and stow will create symlinks for him in the directory
above "~/dotfiles", his home. His ~/dotfiles should look something like this:
bob
`-- dotfiles
|-- bash
| |-- .bash_profile
| `-- .bashrc
|-- config
| `-- .config
|-- mutt
| `-- .mutt
| |-- config_1
| |-- config_2
| `-- config_3
`-- vim
|-- .vim
| |-- bundle
| `-- ftplugin
`-- .vimrc
This means that he can deploy his dotfiles by going into the dotfiles directory
and executing stow bash config mutt vim
, which creates symlinks in ~/,
duplicating the hierarchy he had in place before. Advantages include: being able
to selectively deploy configs only for programs you need on that PC, easy
integration with Git, Mercurial and the like as the dotfiles directory can be
checked into VCS. Stow has certainly avoided me a few headaches, I recommend it
for anyone who needs to use multiple machines.