Use "cd" from within a Bash script

Why the need of this?

Let’s assume you want to write a script that would allow you to navigate faster between your most frequently used directories. And let’s take my everyday problems as an example. I have a similar directory structure:

~/studies/
     semester1/
         subject1/
         subject2/
         ...
     semester2/
         subject1/
         subject2/
         ...
     ...

Every time I want to cd to one of these directories I have to write something like:

cd ~/studies/semester4/subject2

which is a little pain in the arse if I have to do this many times (and I have to). And no, using Nautilus or Thunar or Dolphin or any other graphical tool doesn’t help - clicking is still slower than writing.

So it would be nice if I could just write a little script doing most of the work for me (and by that I mean letting me type only few characters instead of the whole path).

Assuming I’m studying at only one semester at a time and changing one variable every half a year is not a big problem, I came up with this script:

#!/bin/bash

SEMESTER=semester4
ROOTPATH=~/studies/${SEMESTER}/

if [ $# -lt 1 ]; then
  pushd ${ROOTPATH}
else
  cd ${ROOTPATH}/$1*
fi

It just takes the first command line argument, creates a path and does cd. And of course, it doesn’t work.

Why?

As you probably already know there are such misterious things as environment variables. The variable that specifies the current working directory (as returned by pwd command) is PWD. You can even set it by hand:

PWD=/home/yourname/studies/semester4

Environment variables are inherited by child process, but the child process cannot change its parent’s variables. When you invoke a bash script, you’re silently invoking fork and exec and creating a child process with its own set of variables.

The solution

The source command comes in handy. By invoking source some_script.sh you’re “pulling” changes made by the script to the current process. Place our script e.g. in ~/bin/fastcd.sh and run

source ~/bin/fastcd.sh foo

(where foo is the prefix of one of the subjects). Now it works.

But it’s still a little to long, so we’re going to make it shorter.

The power of aliases

Open ~/.bashrc in your favourite text editor and add the line:

alias fast='source ~/bin/fastcd.sh'

And then once again using the source command, run:

source ~/.bashrc

Now you may type:

fast foo

in your terminal, and it will run cd ~/studies/semester4/foo* for you.