Don't let `cd` slow you down

I spend quite a bit of time moving around in the terminal. Naturally, tools like fasd, bd, fzf, etc are at the top of my ‘day-to-day usage list’. Unfortunately, zsh is nowhere among them. As much as I would love to use it, the majority of Linux distributions still don’t have it preinstalled. For me it’s a deal breaker. I honestly don’t want to get homesick every time I ssh into some remote machine I have no control over. The obvious shell of choice, given the circumstances, is Bash. Up until recently, there was one thing driving me nuts, though. Namely, absent zsh-style cd. But, with commacd in the game, it’s no longer a problem.

So, what is commacd exactly? Well, it’s basically just a bunch of aliases (,, ,,, and (surprise, surprise!) ,,,), designed to make navigation faster. The best way to explain each one of them is probably to go through some examples.

Let’s start with ,. Think of it as a cd that matches directories by prefixes:

~$ , des
  => cd Desktop

# move through multiple directories
~$ , /u/l/ce
  => cd /usr/local/Cellar

# allow me to choose directory in case of ambiguous pattern (= multiple choices)
~$ , d
  => 1 Desktop
     : <type index of the directory to cd into>

# given two directories jdk7 and jdk8 on the Desktop, cd into jdk8 without hitting interactive mode (the one shown above)
~/github$ , ~/d/j*8
  => cd ~/Desktop/jdk8

# cd into directory having 'esk' somewhere in its name
~/github$ , ~/*esk
  => cd ~/Desktop

If you often find yourself using cd .., cd ../.., … (in one from or another), you might be interested in ,,. It has a number of different strategies that can make navigation backward a whole lot easier:

  • (no arguments) look for the project (checkout) directory (the one with .git/.hg/.svn in it) and then cd into it;
  • (one argument) cd into the closest parent having its name begin with whatever the value you passed in;
  • (two arguments) replace all occurrences of the first value with the second one (in the current path).
# go all the way up to the project root (in this case, the one that has .git in it)
~/github/lorem/src/public$ ,,
  => cd ~/github/lorem

# cd into to the first parent directory named g*
~/github/vimium/src/public$ ,, g
  => cd ~/github

# substitute jekyll with ghost
~/github/jekyll/test$ ,, jekyll ghost
  => cd ~/github/ghost/test

The last one is ,,, (my favorite). Think of it as , but from the first (nearest) parent directory having non-empty expansion. It allows quickly jump between multiple directories sharing the same ancestor (not necessarily an immediate one).

# jump to some other project (in this case, located in ~/github)
~/github/rook/src/public$ ,,, m*binlog
  => cd ~/github/mysql-binlog-connector-java

Note that all three commands automatically emit pwd before the completion (just like cd -), which makes it possible to combine them with other tools (without actually changing the working directory):

$ tail -f `, /v/l/t/l`/catalina.out
  => tail -f /var/lib/tomcat7/logs/catalina.out

/opt/nginx$ `,,, ap/b`/cassandra-cli
  => /opt/apache-cassandra-1.2.1/bin/cassandra-cli

You can also hit <Tab> whenever you want to check where are you about to jump to. Like this:

$ , /v/l<Tab>
  => (shows 3 possible completions) /var/lib/ /var/lock/ /var/log/

$ , /u/l/ce<Tab>
  => , /usr/local/Cellar/

To shrink path back use <Control>-.

And now, the final part - installation. commacd is written in pure Bash (no dependencies on Python/Ruby/Perl, no nothing). Getting it into your shell is as easy as:

curl -o ~/.commacd.bash && echo "source ~/.commacd.bash" >> ~/.bashrc

After that, open a new terminal session and , ahead!

Want to help out? Report issues, suggest improvements/features or, even better, send in a pull request (see GitHub page). Every bit is helpful.