Why doesn't "cd" work in a shell script?

160,924

Solution 1

As others have explained, the directory is changed in the child process of your script, not in the terminal process from which the script is called. After the child process dies, you are back in the terminal which is left where it was.

Several alternatives:

1. Symbolic link

Put a symlink in your home to the long path you want to easily access

$ ln -s /home/alex/Documents/A/B/C ~/pathABC

then access the directory with:

$ cd ~/pathABC

2. Alias

Put an alias in your ~/.bashrc:

alias pathABC="cd /home/alex/Documents/A/B/C"

(from here)

3. Function

Create a function that changes the directory, the function runs in the process of your terminal and can then change its directory.

(from here)

4. Avoid running as child

Source your script instead of running it. Sourcing (done by . or source) causes the script to be executed in the same shell instead of running in its own subshell.

$ . ./pathABC

(from here and here)

5. cd-able vars

Set the cdable_vars option in your ~/.bashrc and create an environment variable to the directory:

shopt -s cdable_vars
export pathABC="/home/alex/Documents/A/B/C"

Then you can use cd pathABC

(from here)

Solution 2

When you run script in a Terminal, a child process runs. In this child program i.e. your script will change to whatever directory specified. But in the parent process, i.e. where you run the script is still in the old path. OR simply we can say:

The scope of cd command is only for child process not parent.

Solution 3

You are making a thinking error. While the current shell stays in the same directory, the script has moved to the new directory.

You could see that by creating another script in the new directory, and running it from your script, after it has changed directory:

#!/bin/sh
cd /home/alex/Documents/A/B/C && ./another_script.sh # (if it is executable)

The second script would run from the new directory.

HelloWorld 

is just the output of the script.

Solution 4

Actually, I just found, after many searches, that if you need to change the directory, and still keep the same shell, so you will get all the answers in your current script, you can use:

(cd your_dir; do_some_command_there)

For example, what I needed to use, was:

(cd your_dir; git remote -v | wc -l)

Works like a charm!

Solution 5

Trying to use cd inside the shell script does not work because the shell script runs in the subshell and once the script is over it returns to the parent shell, which is why the current directory does not change.

To achieve changing of the directory use sourcing.You can either use . scriptname.sh or source scriptname.sh command to use sourcing.

Note : Also when you use sourcing do not use the exit command because it then closes your connection.

Share:
160,924

Related videos on Youtube

Mohammad Reza Rezwani
Author by

Mohammad Reza Rezwani

Msc of computer networks.

Updated on September 18, 2022

Comments

  • Mohammad Reza Rezwani
    Mohammad Reza Rezwani over 1 year

    I just want to write a script which changes my directory.

    I put the below commands in the file /home/alex/pathABC

    #!/bin/sh
    cd /home/alex/Documents/A/B/C
    echo HelloWorld
    

    I did

    chmod +x pathABC
    

    In the Terminal, while in /home/alex, I ran ./pathABC, but the output is just HelloWorld and the current directory is not changed.

    So what is wrong?

    • TuKsn
      TuKsn almost 10 years
    • Shiwangini Shishulkar
      Shiwangini Shishulkar about 4 years
      'cd' works in a shell script. For example, you might have placed any script onto /home/alex/Documents/A/B/C path and you write shell script like: first it will go to the directory(via cd) then run the script(via ./) then it will. However, after that control will return back to the current path from where you are running ./pathABC script. The same case is happening with your script, it's going to the path and then once execution exits ,it return back to the location from where it's been called.
  • zwets
    zwets almost 10 years
    Adding to this, @alex to achieve the effect you are looking for, execute the script within the parent process by sourcing it: either . pathABC or source pathABC.
  • Mog
    Mog almost 10 years
    HelloWorld is not "returned" to the parent shell, it's output to the standard output
  • hytromo
    hytromo almost 10 years
    Now I understand the usage of source! I always wondered why I do source .bashrc and not bash .bashrc
  • i2097i
    i2097i over 7 years
    Option 3 worked great. I just defined a function go_to_wherever() { cd my/directory } at the beginning of my script. Called it before running the operations in that directory.
  • loxaxs
    loxaxs almost 7 years
    > 5. cd-able vars -- isn't it cd $pathABC ?
  • wjandrea
    wjandrea almost 6 years
    Might be clearer if you just run pwd in the new directory, instead of adding a whole new script to the situation.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 6 years
    @wjandrea That's what you get for coding on a phone! Just got home, I'll fix it up. Thanks. Um just checked and it works fine. Maybe it's your 14.04 version I read about an hour ago or so?
  • wjandrea
    wjandrea almost 6 years
    Well, you totally changed the script. Previously it was just one command: cd /home/mike/Documents/A/B/C, which didn't produce any output. Now it's echo "/home/mike/Documents/A/B/C", which does produce output.
  • WinEunuuchs2Unix
    WinEunuuchs2Unix almost 6 years
    @wjandrea True, I also totally changed the way of calling the script too. Instead of a simple ./cd.sh it's now cd $(./cd.sh) but it accomplishes the goal of the child changing the parent's current directory. Yes it's unconventional but it's another way of doing it that I hope people find interesting.