Quickly Navigate your Filesystem from the Command Line

Jeroen Janssens
Aug 16, 2013 • 6 min read

Update (6-9-2013) This code is now also available as the “jump” plugin in oh-my-zsh.

Update (18-8-2013): Thanks to the many useful suggestions in the discussion on Hacker News, I have added (1) quotes to the code, (2) a section about tab completion, and (3) a note for macOS users.

Like many others, I spend most of my day behind a computer. In order make the most of it (and to keep my body from complaining too much), I try to maintain an optimised setup. For example, I code in Vim, browse with Vimperator, and move windows around in i3. Another common task is filesystem navigation. I prefer to use the command-line for this, but typing cd ~/some/very/deep/often-used/directory over and over again does become cumbersome.

Automated tools like autojump, z, and fasd address this problem by offering shortcuts to the directories you often go to. Personally, I prefer a more manual solution, which I would like to share with you. I have noticed quite an increase in efficiency with this, and perhaps you will too.

Jumping with symbolic links

Under the hood this manual solution comes down to storing symbolic links in a hidden directory (e.g., ~/.marks). There are four shell functions jump, mark, unmark, and marks, and they look like this:

export MARKPATH=$HOME/.marks
function jump {
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" | sed 's/ / /g' | cut -d' ' -f9- | sed 's/ -/\t-/g' && echo
}

Put this in your .zshrc or .bashrc and you’re ready to jump (Mac OS X users need a slightly different version of the marks function; see below). I have also turned this into a plugin for oh-my-zsh called jump. To add a new bookmark, cd into the directory and mark it with a name to your liking:

$ cd ~/some/very/deep/often-used/directory
$ mark deep

This adds a symbolic link named deep to the directory ~/.marks. To jump to this directory, type the following from any place in the filesystem:

$ jump deep

To remove the bookmark (i.e., the symbolic link), type:

$ unmark deep

You can view all marks by typing:

$ marks
deep -> /home/johndoe/some/very/deep/often-used/directory
foo -> /usr/bin/foo/bar

That’s all there is to it!

Adding tab completion

In order to add tab completion for the jump and unmark functions, add the following code to your .zshrc (thanks to tiziano88):

function _completemarks {
reply=($(ls $MARKPATH))
}

compctl -K _completemarks jump
compctl -K _completemarks unmark

or the following to your .bashrc (thanks to microcolonel):

_completemarks() {
local curw=${COMP_WORDS[COMP_CWORD]}
local wordlist=$(find $MARKPATH -type l -printf "%f\n")
COMPREPLY=($(compgen -W '${wordlist[@]}' -- "$curw"))
return 0
}

complete -F _completemarks jump unmark

If you now type jump or unmark and then press TAB, you see a list of available marks. Neat!

Note for macOS users

As pointed out by guygurari, macOS users need a slightly different version of the marks function:

function marks {
\ls -l "$MARKPATH" | tail -n +2 | sed 's/ / /g' | cut -d' ' -f9- | awk -F ' -> ' '{printf "%-10s -> %s\n", $1, $2}'
}

— Jeroen


Would you like to receive an email whenever I have a new blog post, organize an event, or have an important announcement to make? Sign up to my newsletter:
© 2013–2024  Jeroen Janssens