Tristan Le Guern

Poor man’s direnv

I always watched the direnv utility from afar, mumbling something along the lines of “someday I will really need it”. Well someday happened: two projects at $WORK needed each a different value for a specific environment variable in order to handle a version upgrade.

One solution can be to have an initialisation script at the root of each projects and have everyone run it all the time. I have worked at companies where it was the norm but I find it unpleasant and error prone.

A seemingly better solution is to use direnv which can automatically load and unload environment variables depending on the current directory. Seems nice, doesn’t it? It would be perfect if only my favorite shell was supported, alas ksh is not on the list (and probably won’t anytime soon).

To work around this limitation I cooked a small alias doing roughly the same thing (as in “just the core feature and not the nice extra things”):

cd() {
    if [ -f .envrc ]; then
        unset $(cat .envrc | cut -d = -f 1 | cut -d ' ' -f 2)
    fi
    builtin cd "$@" || builtin return $?
    if [ -f .envrc ]; then
        . ./.envrc
    fi
}

Just paste it in your ~/.kshrc (or .mkshrc for MirBSD korn shell, it works too).

Let’s check with direnv’s Quick demo:

# Create a new folder for demo purposes.
$ mkdir ~/my-project
$ cd ~/my-project

# Show that the FOO environment variable is not loaded.
$ echo ${FOO-nope}
nope

# Create a new .envrc. This file contains variables that ksh is going to load.
$ echo export FOO=foo > .envrc

# No security mechanism here nor autoreload feature. Get out and get in again.
$ cd - && cd -

# Show that the FOO environment variable is loaded.
$ echo ${FOO-nope}
foo

# Exit the project.
$ cd ..

# And now FOO is unset again
$ echo ${FOO-nope}
nope

Good enough for me.

Changelog