GNU stow is an underrated tool. Generically, it helps maintain a unified tree of files that come from different sources. More concretely, I use a bunch of software (D compilers, various tools) that I install manually instead of through my system’s package manager (for various reasons). stow makes that maintainable by letting me cleanly add/remove packages and switch between versions. Here’s how it’s done.

The ~/local/ directory

The idea is simple: you stow install all personal software inside a local/ directory inside your home directory. The resulting directory structure looks the same as if you installed the software normally to the filesystem root, so you’ll end up with ~/local/bin and ~/local/lib directories, etc.

Setting up the local/ directory for use with stow is easy. The main thing you need is a local/ directory in your home directory, with a stow/ subdirectory to store package archives:

$ mkdir -p ~/local/stow

If you’re installing programs into your local/ directory, you probably want to add local/bin to your PATH so you can easily use programs there like other programs. You can add this to the end of your ~/.profile file (or whatever init file is used by your shell):

PATH="$HOME/local/bin:$PATH"

Downloading and installing tarball packages

I like tsv-utils, a handy collection of tools for data analysis on the command line. It’s not in the normal package managers I use, but there are pre-compiled tarball archives available. Here’s how to use them with stow.

First, switch to your stow archive directory:

$ cd ~/local/stow

Then download the tarball and extract it:

$ wget https://github.com/eBay/tsv-utils/releases/download/v2.2.0/tsv-utils-v2.2.0_linux-x86_64_ldc2.tar.gz
$ tar xf tsv-utils-v2.2.0_linux-x86_64_ldc2.tar.gz

You’ll now have a directory containing all the package files:

$ tree tsv-utils-v2.2.0_linux-x86_64_ldc2
tsv-utils-v2.2.0_linux-x86_64_ldc2
├── LICENSE.txt
├── ReleasePackageReadme.txt
├── bash_completion
│   └── tsv-utils
├── bin
│   ├── csv2tsv
│   ├── keep-header
│   ├── number-lines
│   ├── tsv-append
│   ├── tsv-filter
│   ├── tsv-join
│   ├── tsv-pretty
│   ├── tsv-sample
│   ├── tsv-select
│   ├── tsv-split
│   ├── tsv-summarize
│   └── tsv-uniq
└── extras
    └── scripts
        ├── tsv-sort
        └── tsv-sort-fast

4 directories, 17 files

You can delete the .tar.gz archive if you want.

Now you can install the package into local/ with stow:

$ stow tsv-utils-v2.2.0_linux-x86_64_ldc2

That creates a bunch of symbolic links inside the parent directory (~/local/) pointing to files and directories inside the package directory (~/local/stow/tsv-utils-v2.2.0_linux-x86_64_ldc2).

If you’ve set your PATH (you might need to restart your shell), you’ll now be able to run tsv-utils commands normally:

$ tsv-summarize --help
Synopsis: tsv-summarize [options] file [file...]

tsv-summarize runs aggregation operations on fields in tab-separated value
files. Operations can be run against the full input data or grouped by key
fields. Fields can be specified either by field number or field name. Use
'--help-verbose' for more detailed help.

Options:

[*snip*]

Removing and upgrading packages

Okay, stow’s algorithm for managing symbolic links is neat, but so far there’s no practical benefit over extracting the tarball directly into local/. stow shines when you’re maintaining your package collection. For example, if you decide to uninstall tsv-utils later, you just need to switch to the archive directory and run stow again with the -D flag:

$ cd ~/local/stow
$ stow -D tsv-utils-v2.2.0_linux-x86_64_ldc2

That will cleanly remove tsv-utils from the local/ directory without breaking any other installed packages. Try doing that after extracting the tarball directly to local/.

The package directory inside the stow/ directory will remain, but you can delete that too, if you want, of course.

stow doesn’t manage versions, so upgrading packages means uninstalling the old package and installing the new package. stow detects when packages collide (e.g., they both include a file called bin/tsv-summarize), so you can only install one version at a time. However, you can keep as many archive directories as you like in stow/, allowing you to easily switch back and forth between versions if you need to.

Building packages from source

Not all software comes precompiled. Sometimes you’re experimenting with your own custom version. If you want to use source packages with stow, you just need to figure out how to make the source package install to a directory in your stow/ directory, instead of your filesystem root.

Suppose I want to install my own version of the GraphicsMagick image processing tools. This will be a two-stage process. First I’ll need to download and extract the source somewhere (I keep a src/ directory for third-party source code).

$ cd ~/src
$ wget -O GraphicsMagick-1.3.36.tar.gz https://sourceforge.net/projects/graphicsmagick/files/graphicsmagick/1.3.36/GraphicsMagick-1.3.36.tar.gz/download
$ tar xf GraphicsMagick-1.3.36.tar.gz
$ cd GraphicsMagick-1.3.36

GraphicsMagick uses a GNU-style build system using autotools. configure scripts take a --prefix option that sets the installation root.

$ ./configure --prefix="$HOME/local/stow/GraphicsMagick-1.3.36"
$ make install

The installation step automatically creates the stow/GraphicsMagick-1.3.36/ directory. Now I just need to install the built package with stow.

$ cd ~/local/stow
$ stow GraphicsMagick-1.3.36
$ gm version
GraphicsMagick 1.3.36 20201226 Q8 http://www.GraphicsMagick.org/
Copyright (C) 2002-2020 GraphicsMagick Group.
Additional copyrights and licenses apply to this software.
See http://www.GraphicsMagick.org/www/Copyright.html for details.

[*snip*]

Other uses

This is my personal favourite usage of stow, but it’s just a generic tool for merging multiple filesystem trees in a maintainable way. Some people use it to manage their /etc/ configuration files, for example. If you try it out, I’m sure you can find other use cases.