Jumping quickly between deep directories

I often need to jump between different directories with very deep paths, like this:

$ cd some/very/deep/directory/project1
$ # do stuff in Project 1
$ cd different/very/deep/directory/project2
$ # do stuff in Project 2

While it only takes a handful of seconds to switch directories, the extra mental effort often derails my train of thought. Some solutions exist, but they all have their limitations. For example, pushd and popd don’t work well for directories you haven’t visited in a while. Aliases require you to manually add a new alias to your .bashrc every time you want to save a new directory.

I recently found a solution, inspired by this post from Jeroen Janssens, that works great and feels totally natural. All it takes is a one-time change to your .bashrc that will allow you to easily save directories and switch between them. To save a directory, just use the mark function:

$ pwd
some/very/deep/directory/project1
$ mark project1

To navigate to a saved directory, just use the cdd function:

$ cdd project1
# do stuff in Project 1
$ cdd project2
# do stuff in Project 2

You can display a list of your saved directories with the marks function, and you can remove a directory from the list with the unmark function:

$ unmark project1

For any of this to work, you’ll need to add this to your .bashrc, assuming you have a Mac and use the bash shell.

    function cdd {
        cd -P "$MARKPATH/$1" 2>/dev/null || echo "No such mark: $1"
    }
    function mark {
        mkdir -p "$MARKPATH"; ln -s "$(pwd)" "$MARKPATH/$1"
    }
    function unmark {
        rm -i "$MARKPATH/$1"
    }
    function marks {
        \ls -l "$MARKPATH" | tail -n +2 | sed 's/  / /g' | cut -d' ' -f9- | awk -F ' -> ' '{printf "%-10s -> %s\n", $1, $2}'
    }

    _cdd()
    {
        local cur=${COMP_WORDS[COMP_CWORD]}
        COMPREPLY=( $(compgen -W "$( ls $MARKPATH )" -- $cur) )
    }
    complete -F _cdd cdd

This differs from Jeroen’s original code in a couple of ways. First, to be more brain-friendly, it names the function “cdd” instead of “jump”. Second, the tab completion works better.

Update: John McDonnell points me to autojump.