Navigating several layers of nested directories is often a pain. On Firefox, it is easy because they have bookmarks. So what I'd like to do to bookmarks a file is to type:

$ go --add classes "repo/www/public/util/classes"

Then, to go to this directory, I'd type:

$ go classes

Previously I've used symbolic links, to achieve something similar, but I don't want to clutter up my home directory. There are lots of other features that could prove useful. For example, I would like to able to start typing go cl and then hit tab to autocomplete. Sometimes I have multiple copies of a repository checked out and so it would be useful for the program to allow me to create multiple contexts and to set the bookmark relative to the context base directory.

So, before I set off on cobbling my own set of scripts together, is there already something like this?


17 Answers 17


I think you're looking for something like autojump. You have to cd around a bit to develop a set of "key weights" that correlate with the amount of time spent in a given directory. Then, assuming you spent a lot of time in that 'classes' dir, you could jump there directly by typing

j cl

You can view your "key weights" with

  • I recently found a little more complex, but interesting, and related, tool called f : github.com/clvv/f
    – tcdyl
    Dec 22 '11 at 6:57

As saeedn mentions, aliases are a good mechanism. The bash shell also has a built-in mechanism to jump right to a location: CDPATH. Set it like PATH, but it is used by cd instead of searching for programs.

$ CDPATH=:~/repo/www/public/util
$ cd classes

From the manpage:

   CDPATH The search path for the cd command.  This is  a  colon-separated
          list  of  directories  in  which the shell looks for destination
          directories specified by the cd  command.   A  sample  value  is

Myself, I've combined this with a directory that has symlinks to where I'd want to go:

$ mkdir ~/cdshortcut
$ ln -s ~/repo/www/public/util/classes ~/cdshortcut/classes
$ CDPATH=:~/cdshortcut

This has the drawback that the directory doesn't quite appear to be correct, but that can be rectified using cd -P or setting set -P.

  • CDPATH is interesting, but it is probably worth using a separate go command so that the behaviour is always predictable
    – Casebash
    Dec 14 '11 at 11:36
  • 1
    +1 for set -P. Some of my symlinks were driving me crazy because I couldn't remember where they really went and didn't remember the command that shows that information.
    – Joe
    Dec 17 '11 at 21:52
  • @Joe, I would add alias C='cd -P .' rather than set -P, since for system symlinks I don't mind being in the symlink directory.
    – Wildcard
    Nov 10 '16 at 8:15
  • @Wildcard - interesting - could you give an example where this makes a difference to you? I just ran help cd and still don't understand what the -P option does.
    – Joe
    Nov 11 '16 at 21:54
  • @Joe mkdir test; ln -s test linktotest; cd linktotest; pwd; cd -P .; pwd
    – Wildcard
    Nov 11 '16 at 22:15

I was looking for some shell-bookmarking tool for too long, and I'm not satisfied with any of the solutions I found.

However, eventually I've come across a great, universal tool: command-line fuzzy finder.

It primarily allows you to “fuzzy-find” files (check the rich gif animation by the link above), but it also allows to feed arbitrary text data to it and filter this data. So, the shortcuts idea is simple: all we need is to maintain a file with paths (which are shortcuts), and fuzzy-filter this file. Here's how it looks: we type cdg command (from “cd global”, if you like), get a list of our bookmarks, pick the needed one in just a few keystrokes, and press Enter. Working directory is changed to the picked item:


It is extremely fast and convenient: usually I just type 3-4 letters of the needed item, and all others are already filtered out. Additionally, of course we can move through list with arrow keys or with Ctrl+j/Ctrl+k.

Detailed article about this shortcuts/bookmarks solution is here: Fuzzy shortcuts for your shell.


You could combine Bash's existing history and history searching features. Press Ctrl-R to begin incremental reverse searching, then start typing the part of the path most likely to be unique.

You can keep typing letters until you end up back at the most recent cd command involving that directory, or you can press Ctrl-R again to jump back in history to the next newest command matching what you've typed so far.

I do this all the time.

Actually, I take it a step further. Once I start discovering sequences of commands worth keeping in history but not worth committing to a shell script, I start chaining them up with && and ; combinators so I can reverse-search for a substring of that one long command, hit Enter and run the whole sequence at once.

For example, here's how I build and run one of my programs during development:

$ ( cd .. ; make install ) && ./start_my_program

I do this from the install directory, which is underneath the top-level source directory. By wrapping the cd, build and install part in a sub-shell, I ensure that no matter what happens during this process, I end up back in my normal shell with nothing changed. Only if that succeeds (&&) do I start the built and installed program. I can find this in my history with just a Ctrl-R then sta, that being all I usually need to uniquely find this command sequence.

Another example of how I use this is the sequence that goes into building RPMs for this same program. Most of the tedious work is in shell scripts, but there are still a few commands I'd normally have to type to do all the work of building and deploying the built RPMs, which I now rarely have to re-type, because Bash keeps it in history for me.

Combine all this with export HISTSIZE=bignum and shopt histappend and you have just built an elephantine command memory.

Another solution I coded up once is in my answer to another question here. It might have to be tailored for your purposes, and it only handles cd commands, whereas the history searching option works everywhere and for every command.


I myself use alias to shorten long paths which I visit often. You can put your set of aliases in your bashrc, so bash could remember them every time you login. And fortunately bash adds aliases to auto complete.

I would write something like this for your case: alias go-classes="cd ~/repo/www/public/util/classes"


You might be looking for bashmarks (on github).
From the README:

Bashmarks is a shell script that allows you to save and jump to commonly used directories. Now supports tab completion.


This is in no way complete nor fool-proof, just a draft to start with. By adding the following in your ~/.bashrc you'll have three commands to add delete and list directory bookmarks (which are based on shell aliases, so you kind of getting auto-completion too).

[ -f "$BMFILE" ] && . "$BMFILE"

bmadd() {
    local abm
    if [[ $# = 0 ]]; then
        bm=$(basename $(pwd))

    abm="alias $bm='cd \"$(pwd)\"'"

    if grep -q " $bm=" "$BMFILE"; then
        echo "Overwriting existing bookmark $bm"
        bmdel "$bm"
    echo "$abm" >> "$BMFILE"
    eval "$abm"
    #source "$BMFILE"

bmdel() {
    local bms
    if [[ $# = 0 ]]; then
        bm=$(basename $(pwd))

    #sed -i.bak "/ $bm=/d" "$BMFILE"
    bms=$(grep -v " $bm=" "$BMFILE")
    echo "$bms" > "$BMFILE"
    unalias "$bm" 2> /dev/null

bmlist() {
    sed 's/alias \(.*\)=.cd "\(.*\)".$/\1\t\2/' "$BMFILE" | sort

Usage is pretty simple. bmadd with an argument adds an alias named after the argument. This alias just makes a cd to the directory it was set in. Without an argument it uses the current dirname as the alias name. In similar way, bmdel deletes an alias if exists and bmlist lists current bookmarks.


u@h:~ $ cd /usr/share/doc
u@h:/usr/share/doc $ bmadd
u@h:/usr/share/doc $ cd /usr/local/share/
u@h:/usr/local/share $ bmadd lshare
u@h:/usr/local/share $ cd
u@h:~ $ bmlist
doc     /usr/share/doc
lshare  /usr/local/share
u@h:~ $ doc
u@h:/usr/share/doc $ bmdel lshare
u@h:/usr/share/doc $ bmlist
doc     /usr/share/doc
u@h:/usr/share/doc $

I came across the same need awhile ago and decided to put together a couple of scripts to help me bookmark absolute/relative paths and map them to shorter names that I can remember easily.

The script is very easy to use and it will simply create a function with the short name that you provide as an alias to the directory that you want to jump into. All what you need to do is simply typing that short name and it will take your through to the bookmarked directory.

Here is a link to the source of the bookmarker script. By the way, I named it The Bookmarker.


Once installed it's pretty trivial to use.

To mark a directory:

$ mark /this/is/a/very/very/looooong/path mydir

To navigate to a marked dirctory:

$ mydir

To see what's been marked:

$ marks
bin     -> /Users/khafaji/bin
eBooks  -> /Users/khafaji/eBooks

To delete a marked directory:

$ umark myDir

For further examples, installation instructions etc. see the very detailed documentation.


cdargs is the best tool for directory bookmarking.

For usage examples see the bookmarks for the cd command video on YouTube.

Example Usage

cdargs is a ncurses GUI so you can visually navigate within your shell. Once it's installed you set it up in a given shell by sourcing a shell script:

$ source /etc/profile.d/cdargs.sh

This enables several functions that you can then call from your shell.

Summon the GUI:

$ cv

Resulting in this type of a GUI:

   [.       ]  /home/saml/tst/88040
 0 [path0   ]  /home/saml/tst/88040/path0
 1 [path1   ]  /home/saml/tst/88040/path1
 2 [path2   ]  /home/saml/tst/88040/path2

You can use your arrow keys to move up and down to navigate the list. The left arrow () goes up a level in the directory tree, a right arrow () will drill down into a directory.

marking directories:

You can either use c for the current directory you navigating or you can use a to add the directory that you're currently highlighting with the cursor.

operation modes:

cdargs is a little like vi/vim in this regard where it has this notion of modes. There are 2 of them, browsing (B) and listing (L). You can see which mode you're in through the display at the bottom of your shell.

Listing mode:

L: /home/saml/tst/88038

Browsing mode:

B: /home/saml/tst/88038

You can alter your mode by hitting the tab key (TAB).

This is just the tip of the iceberg, consult the man page (man cdargs) and also the built-in help for more information.


The best tool for this is: wcd. I have tested many other tools, and this one is used exactly in the way you are asking and it is better in many senses than all the previous solutions.


The other answers are great and specific. Another way to look at it is to use a keyboard macro processor that can do almost anything you can think of.

Check out AutoKey. It can substitute phrases like a word processor autocorrect or bash history and it can also run a python script on a hotkey you define which can do almost anything and also send keystrokes to your character input device - just as if you typed them.

The only "shortcoming" it has (in relation to this question) is that it needs a gui to run in - gnome or kde. The other answers don't have this requirement.


There is an another alternative called z.

It learns on every directory change:

$ cd /tmp/
$ pwd
$ cd
$ pwd

Then you can change to that directory later with fuzzy matching:

$ z mp
$ pwd

Apparix is another tool that does this. One of its useful features is that you can jump directly to subdirectories of the mark and tab-complete on those sub-directories.


E. Todd Allen's "marks" have been my goto for over 20 years. Mark a folder, and it's available as a "cd" alias as well as a shell variable.

$ cd /my/long/obscure/pathname/delving/deep/into/the/kernel/source
$ mark driver
$ cd /somewhere/else/entirely/even/weeks/later
$ mark otherspace
$ cp $driver/source.cpp
$ ls source.cpp
$ pwd
$ driver
$ marks

Another solution that, I believe, is to autojump and z is fasd.

It keeps track of which directories you visit and z dir-name will change to the directory with the name dir-name that you use most frequently. It also has some functionality for frequently used files.

You can clone it from: https://github.com/clvv/fasd

Installing is straight-forward, clone, make install, and then modify your .bashrc (or .zshrc etc).


You need to add an alias to your .bashrc or .bash_profile.

## navigate to your home directory
$ cd ~
## list the contents of your home directory to see if you have `.bashrc` or `.bash_profile`
$ ls -a 
[`.bashrc` or `.bash_profile` should appear in the list]
## launch the text editor of your choice; I'll use vim here
## if no `~/.bashrc` or `~/.bash_profile`...
$ vim
## if, e.g., `~/.bash_profile` listed...
$ vim ~/.bash_profile

Now, let's say you want a shortcut to ~/Desktop/Coding/Projects, to invoke which you will type goto_Projs. You need to add the following line to the file open in the text editor:

alias goto_Projs='cd ~/Desktop/Coding/Projects'

Now do whatever your text editor wants you to do to save (to /User/<yourusername>/ or ~/ of course) and exit, and when the shell prompt is returned go

source ~/.bash_profile

Your alias should now be available to invoke as described above.


I use the method of appending a comment at the end of the command and then invoking ctrl R to reverse search for the comment. This has the following advantages:

  • search for a command in natural language
  • change the comment any time on the fly and get the latest update from ctrl R
  • use ctrl R and tab on the fly to make minor tweaks to the command itself, thus making the comment a kind of generic shortcut to a family of similar commands
  • no setups, installs, or book keeping required :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.