Why I can't change directories using "cd"?


I'm trying to write a small script to change the current directory to my project directory:

cd /home/tree/projects/java

I saved this file as proj, added execute permission with chmod, and copied it to /usr/bin. When I call it by: proj, it does nothing. What am I doing wrong?

6/26/2020 8:09:40 PM

Accepted Answer

Shell scripts are run inside a subshell, and each subshell has its own concept of what the current directory is. The cd succeeds, but as soon as the subshell exits, you're back in the interactive shell and nothing ever changed there.

One way to get around this is to use an alias instead:

alias proj="cd /home/tree/projects/java"
5/8/2014 1:18:46 PM

The cd in your script technically worked as it changed the directory of the shell that ran the script, but that was a separate process forked from your interactive shell.

A Posix-compatible way to solve this problem is to define a shell procedure rather than a shell-invoked command script.

jhome () {
  cd /home/tree/projects/java

You can just type this in or put it in one of the various shell startup files.


The cd is done within the script's shell. When the script ends, that shell exits, and then you are left in the directory you were. "Source" the script, don't run it. Instead of:



. ./

(Notice the dot and space before the script name.)


To make a bash script that will cd to a select directory :

Create the script file

# file : /scripts/cdjava
cd /home/askgelal/projects/java

Then create an alias in your startup file.

# file /scripts/
alias cdjava='. /scripts/cdjava'

  • I created a startup file where I dump all my aliases and custom functions.
  • Then I source this file into my .bashrc to have it set on each boot.

For example, create a master aliases/functions file: /scripts/
(Put the alias in this file.)

Then at the end of your .bashrc file:

source /scripts/

Now its easy to cd to your java directory, just type cdjava and you are there.


You can use . to execute a script in the current shell environment:

. script_name

or alternatively, its more readable but shell specific alias source:

source script_name

This avoids the subshell, and allows any variables or builtins (including cd) to affect the current shell instead.


Jeremy Ruten's idea of using a symlink triggered a thought that hasn't crossed any other answer. Use:


The leading colon is important; it means that if there is a directory 'dir' in the current directory, then 'cd dir' will change to that, rather than hopping off somewhere else. With the value set as shown, you can do:

cd java

and, if there is no sub-directory called java in the current directory, then it will take you directly to $HOME/projects/java - no aliases, no scripts, no dubious execs or dot commands.

My $HOME is /Users/jleffler; my $CDPATH is:


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Email: [email protected]