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"

compie's user avatar

compie

10.5k15 gold badges58 silver badges79 bronze badges

answered Nov 1, 2008 at 2:09

Greg Hewgill's user avatar

Greg HewgillGreg Hewgill

994k192 gold badges1.2k silver badges1.3k bronze badges

9

You're doing nothing wrong! You've changed the directory, but only within the subshell that runs the script.

You can run the script in your current process with the "dot" command:

. proj

But I'd prefer Greg's suggestion to use an alias in this simple case.

answered Nov 1, 2008 at 2:09

Adam Liss's user avatar

Adam LissAdam Liss

48.3k13 gold badges114 silver badges152 bronze badges

9

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.

answered Aug 11, 2011 at 4:20

DigitalRoss's user avatar

DigitalRossDigitalRoss

146k25 gold badges252 silver badges332 bronze badges

7

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:

./myscript.sh

do

. ./myscript.sh

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

Boann's user avatar

Boann

50k16 gold badges124 silver badges152 bronze badges

answered Feb 10, 2010 at 12:07

Tzachi.e's user avatar

Tzachi.eTzachi.e

1,8311 gold badge11 silver badges2 bronze badges

6

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

Create the script file

#!/bin/sh
# file : /scripts/cdjava
#
cd /home/askgelal/projects/java

Then create an alias in your startup file.

#!/bin/sh
# file /scripts/mastercode.sh
#
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/mastercode.sh

(Put the alias in this file.)

Then at the end of your .bashrc file:

source /scripts/mastercode.sh

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

tripleee's user avatar

tripleee

190k36 gold badges313 silver badges360 bronze badges

answered May 6, 2010 at 3:41

Matt Thomas's user avatar

Matt ThomasMatt Thomas

1,4651 gold badge11 silver badges3 bronze badges

3

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.

that other guy's user avatar

answered Feb 10, 2014 at 11:59

Sagar's user avatar

SagarSagar

1,3359 silver badges15 bronze badges

0

Use exec bash at the end

A bash script operates on its current environment or on that of its children, but never on its parent environment.

However, this question often gets asked because one wants to be left at a (new) bash prompt in a certain directory after execution of a bash script from within another directory.

If this is the case, simply execute a child bash instance at the end of the script:

#!/usr/bin/env bash
cd /home/tree/projects/java
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
exec bash

To return to the previous, parental bash instance, use Ctrl+D.

Update

At least with newer versions of bash, the exec on the last line is no longer required. Furthermore, the script could be made to work with whatever preferred shell by using the $SHELL environment variable. This then gives:

#!/usr/bin/env bash
cd desired/directory
echo -e '\nHit [Ctrl]+[D] to exit this child shell.'
$SHELL

answered Apr 21, 2016 at 11:34

Serge Stroobandt's user avatar

Serge StroobandtSerge Stroobandt

31.6k9 gold badges120 silver badges109 bronze badges

7

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

CDPATH=:$HOME/projects

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:

:/Users/jleffler:/Users/jleffler/mail:/Users/jleffler/src:/Users/jleffler/src/perl:/Users/jleffler/src/sqltools:/Users/jleffler/lib:/Users/jleffler/doc:/Users/jleffler/work

answered Nov 1, 2008 at 4:21

Jonathan Leffler's user avatar

Jonathan LefflerJonathan Leffler

755k145 gold badges947 silver badges1.3k bronze badges

0

I got my code to work by using. <your file name>

./<your file name> dose not work because it doesn't change your directory in the terminal it just changes the directory specific to that script.

Here is my program

#!/bin/bash 
echo "Taking you to eclipse's workspace."
cd /Developer/Java/workspace

Here is my terminal

nova:~ Kael$ 
nova:~ Kael$ . workspace.sh
Taking you to eclipe's workspace.
nova:workspace Kael$ 

answered Oct 28, 2012 at 19:42

kaelhop's user avatar

kaelhopkaelhop

3994 silver badges5 bronze badges

4

simply run:

cd /home/xxx/yyy && command_you_want

answered Mar 10, 2017 at 14:33

warhansen's user avatar

warhansenwarhansen

7361 gold badge8 silver badges25 bronze badges

0

When you fire a shell script, it runs a new instance of that shell (/bin/bash). Thus, your script just fires up a shell, changes the directory and exits. Put another way, cd (and other such commands) within a shell script do not affect nor have access to the shell from which they were launched.

answered Nov 1, 2008 at 2:09

Daniel Spiewak's user avatar

Daniel SpiewakDaniel Spiewak

55.1k14 gold badges112 silver badges121 bronze badges

You can do following:

#!/bin/bash
cd /your/project/directory
# start another shell and replacing the current
exec /bin/bash

EDIT: This could be 'dotted' as well, to prevent creation of subsequent shells.

Example:

. ./previous_script  (with or without the first line)

answered Nov 1, 2008 at 2:46

Thevs's user avatar

ThevsThevs

3,2532 gold badges22 silver badges32 bronze badges

8

On my particular case i needed too many times to change for the same directory. So on my .bashrc (I use ubuntu) i've added the

1 -

$ nano ~./bashrc

 function switchp
 {
    cd /home/tree/projects/$1
 }

2-

$ source ~/.bashrc

3 -

$ switchp java

Directly it will do: cd /home/tree/projects/java

Hope that helps!

answered Sep 14, 2012 at 10:53

workdreamer's user avatar

workdreamerworkdreamer

2,8561 gold badge36 silver badges37 bronze badges

2

You can combine Adam & Greg's alias and dot approaches to make something that can be more dynamic—

alias project=". project"

Now running the project alias will execute the project script in the current shell as opposed to the subshell.

answered Feb 9, 2012 at 7:33

rjmoggach's user avatar

rjmoggachrjmoggach

1,47016 silver badges28 bronze badges

1

It only changes the directory for the script itself, while your current directory stays the same.

You might want to use a symbolic link instead. It allows you to make a "shortcut" to a file or directory, so you'd only have to type something like cd my-project.

answered Nov 1, 2008 at 2:10

Paige Ruten's user avatar

Paige RutenPaige Ruten

177k37 gold badges182 silver badges199 bronze badges

1

You can combine an alias and a script,

alias proj="cd \`/usr/bin/proj !*\`"

provided that the script echos the destination path. Note that those are backticks surrounding the script name. 

For example, your script could be

#!/bin/bash
echo /home/askgelal/projects/java/$1

The advantage with this technique is that the script could take any number of command line parameters and emit different destinations calculated by possibly complex logic.

knuton's user avatar

knuton

3,5973 gold badges26 silver badges23 bronze badges

answered Nov 3, 2008 at 17:22

J. A. Faucett's user avatar

1

Community's user avatar

answered Nov 2, 2008 at 12:50

Gene T's user avatar

Gene TGene T

5,1761 gold badge26 silver badges25 bronze badges

0

In your ~/.bash_profile file. add the next function

move_me() {
    cd ~/path/to/dest
}

Restart terminal and you can type

move_me 

and you will be moved to the destination folder.

answered Aug 19, 2013 at 4:53

mihai.ciorobea's user avatar

You can use the operator && :

cd myDirectory && ls

answered Mar 24, 2013 at 16:56

Jack Bauer's user avatar

Jack BauerJack Bauer

471 silver badge1 bronze badge

1

While sourcing the script you want to run is one solution, you should be aware that this script then can directly modify the environment of your current shell. Also it is not possible to pass arguments anymore.

Another way to do, is to implement your script as a function in bash.

function cdbm() {
  cd whereever_you_want_to_go
  echo "Arguments to the functions were $1, $2, ..."
}

This technique is used by autojump: http://github.com/joelthelion/autojump/wiki to provide you with learning shell directory bookmarks.

inanutshellus's user avatar

answered Feb 1, 2014 at 12:40

thomasd's user avatar

thomasdthomasd

1,0229 silver badges14 bronze badges

You can create a function like below in your .bash_profile and it will work smoothly.

The following function takes an optional parameter which is a project. For example, you can just run

cdproj

or

cdproj project_name

Here is the function definition.

cdproj(){
    dir=/Users/yourname/projects
    if [ "$1" ]; then
      cd "${dir}/${1}"
    else
      cd "${dir}"
    fi
}

Dont forget to source your .bash_profile

tripleee's user avatar

tripleee

190k36 gold badges313 silver badges360 bronze badges

answered Aug 4, 2016 at 15:05

Krish's user avatar

KrishKrish

4771 gold badge8 silver badges16 bronze badges

0

This should do what you want. Change to the directory of interest (from within the script), and then spawn a new bash shell.

#!/bin/bash

# saved as mov_dir.sh
cd ~/mt/v3/rt_linux-rt-tools/
bash

If you run this, it will take you to the directory of interest and when you exit it it will bring you back to the original place.

root@intel-corei7-64:~# ./mov_dir.sh

root@intel-corei7-64:~/mt/v3/rt_linux-rt-tools# exit
root@intel-corei7-64:~#

This will even take you to back to your original directory when you exit (CTRL+d)

Developer Guy's user avatar

answered May 2, 2018 at 23:54

jithu83's user avatar

jithu83jithu83

5791 gold badge6 silver badges11 bronze badges

1

I did the following:

create a file called case

paste the following in the file:

#!/bin/sh

cd /home/"$1"

save it and then:

chmod +x case

I also created an alias in my .bashrc:

alias disk='cd /home/; . case'

now when I type:

case 12345

essentially I am typing:

cd /home/12345

You can type any folder after 'case':

case 12

case 15

case 17

which is like typing:

cd /home/12

cd /home/15

cd /home/17

respectively

In my case the path is much longer - these guys summed it up with the ~ info earlier.

Asclepius's user avatar

Asclepius

63.5k19 gold badges186 silver badges156 bronze badges

answered Apr 11, 2011 at 21:42

chris's user avatar

chrischris

292 bronze badges

1

If you are using fish as your shell, the best solution is to create a function. As an example, given the original question, you could copy the 4 lines below and paste them into your fish command line:

function proj
   cd /home/tree/projects/java
end
funcsave proj

This will create the function and save it for use later. If your project changes, just repeat the process using the new path.

If you prefer, you can manually add the function file by doing the following:

nano ~/.config/fish/functions/proj.fish

and enter the text:

function proj
   cd /home/tree/projects/java
end

and finally press ctrl+x to exit and y followed by return to save your changes.

(NOTE: the first method of using funcsave creates the proj.fish file for you).

answered Dec 12, 2012 at 16:46

Lane Roathe's user avatar

Lane RoatheLane Roathe

5004 silver badges7 bronze badges

You need no script, only set the correct option and create an environment variable.

shopt -s cdable_vars

in your ~/.bashrc allows to cd to the content of environment variables.

Create such an environment variable:

export myjava="/home/tree/projects/java"

and you can use:

cd myjava

Other alternatives.

Community's user avatar

answered Sep 9, 2016 at 7:27

Gauthier's user avatar

GauthierGauthier

42k12 gold badges66 silver badges103 bronze badges

It is an old question, but I am really surprised I don't see this trick here

Instead of using cd you can use

export PWD=the/path/you/want

No need to create subshells or use aliases.

Note that it is your responsibility to make sure the/path/you/want exists.

answered Feb 27, 2020 at 6:33

Yuri Nudelman's user avatar

Yuri NudelmanYuri Nudelman

2,9432 gold badges20 silver badges26 bronze badges

0

I have to work in tcsh, and I know this is not an elegant solution, but for example, if I had to change folders to a path where one word is different, the whole thing can be done in the alias

a alias_name 'set a = `pwd`; set b = `echo $a | replace "Trees" "Tests"` ; cd $b'

If the path is always fixed, the just

a alias_name2 'cd path/you/always/need'

should work In the line above, the new folder path is set

answered Sep 16, 2020 at 19:41

ZakS's user avatar

ZakSZakS

1,1313 gold badges16 silver badges30 bronze badges

1

This combines the answer by Serge with an unrelated answer by David. It changes the directory, and then instead of forcing a bash shell, it launches the user's default shell. It however requires both getent and /etc/passwd to detect the default shell.

#!/usr/bin/env bash
cd desired/directory
USER_SHELL=$(getent passwd <USER> | cut -d : -f 7)
$USER_SHELL

Of course this still has the same deficiency of creating a nested shell.

answered Oct 25, 2020 at 23:49

Asclepius's user avatar

AsclepiusAsclepius

63.5k19 gold badges186 silver badges156 bronze badges

instead of excute a script file and cd to the certain folder,

we can make it by:

  • source or . certain shell script
  • alias the cd command
  • define a function ant cd to folder

examples:

. script
# or
source script
alias ghqc='cd $(ghq root)/$(ghq list | fzf)'
ghqc() {
  cd $(ghq root)/$1
}

answered Apr 9, 2022 at 23:58

zyfyy's user avatar

zyfyyzyfyy

3634 silver badges11 bronze badges

1