I've read this question and answer, but it doesn't quit fit my problem, even tho it's similar.

I'm writing a script (called cpj) that will launch one of my current projects. I have about 5 of them. When I type

$ cpj blah

I want the current working directory to change to the blah project directory (which I hold in $PROJDIR) and I want emacsclient to open the main file for that project (which I hold in $MAINFILE).

The question I cited says that you can't directly change the environment of the shell running the script, but you can source a script and it will do so.

To test this I wrote a shell script (called chcwd) which has one line:

cd $1

If, from the command line I do:

$ . chcwd $PROJDIR

my current working directory will change as I desire. If, on the other hand, from my cpj script, I have the same line:

. chcwd $PROJECT

it will not change the current working directory of the shell. I realize that I'm running 2 scripts (cpj and then chcwd), and so creating 2 shells, but I see no way to get done what I want. Can anyone show me how to accomplish my goal?

3 Answers 3


You can't have your cake an eat it too. The two things happening here are executing a script in a new shell and importing lines of script to be run in the current shell. By using the dot operator (which is an alias for the source command) you are actually running the code in your current shell. If your code chooses to cd, when it's done you will be left in the new directory.

If on the other hand you want to execute a program (or script, it doesn't matter), that program will be launched as a sub-process. In the case of shell scripts a new shell will be opened and the code run inside it. Any cd action taken will change the current working directory for that shell, effective for any commands to follow. When the job finishes the shell will exit, leaving you back in your original (and unmodified) shell.

If it's something you use a lot and you want its effects to be left behind in your current shell, perhaps you could write your "script" as a shell function instead and save it in your ~/.profile or other shell rc file.

function cpj() {
    # code here
    cd /path/$1
    emacs file_name
  • Caleb, thx for your input. I like your pun. Your first paragraph restates what I said in my question admirably. Your second paragraph restates what was said in the question I cited quite well. Your third paragraph is exactly and precisely what I was looking for! Thanks dude.
    – bev
    Commented Jun 10, 2011 at 1:09

I have similar script written for my personal use. There is a very easy trick to achieve change working directory inside a script. First just write your script, in.ex.:


case $1 in
     project1) cd /home/me/work/customer1/project1
     project2) cd /home/me/work/customer2/project1
     project3) cd /home/me/work/customer3/project2
     project4) cd /home/me/work/customer4/project5
     *) echo "Usage: cdto cd_profile_name"

Now lets assume the script is called 'cdto'. To make it working you have to source it in the current shell, what can be achieved by 'source' or '.' command (both are the same). In ex.:

. cdto project1

Now to make it more convenient:

  1. Copy 'cdto' script to a 'bin' directory of your account (in. ex. /home/johnsmith/bin - create it if not exists). Check your PATH variable to ensure the 'bin' directory is included:

    echo $PATH

If not, edit your .profile file and add:

if [ -d "$HOME/bin" ] ; then
  1. Add an alias to your .bashrc or .bash_aliases file:

    alias cdto='. cdto'

And it's done. After next login or when you open a new terminal you could just use in.ex.:

cdto project1

Enjoy :-)

Sebastian Piech


A simple trick to do this:

pushd $PROJDIR && bash

Now the working dir is $PROJECT .

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .