This question already has an answer here:
-
Why doesn't “cd” work in a shell script?
29 answers
I 'm wondering of any mechanism that one could use to change the directory of a parent shell from sub-shell. For ex., I 'm running the script "settings.sh" in my $HOME. My $HOME has a directory $HOME/TEST/run. If my "settings.sh" scripts is as below
#!/bin/bash
# some shell related code
# some shell related code
cd $HOME/TEST/run
exit 0
I execute the above script at command prompt at $HOME. After the execution, I expect my command prompt in directory $HOME/TEST/run. I do understand that in sub-shell, it is being cd'd to $HOME/TEST/run, but at the end of the execution, it's back in $HOME.
Is there any elegant way of doing the above, using a single script. One way is to modify the script "settings.sh" to generate another script and then use ". $HOME/generatedScript.sh"
Nope, you can't. That's by design. Parent processes should never be affected by the results of a child without them wanting to be affected (otherwise sub-shells could do all sorts of nasty tricky things to the parent).
What you can do is have the shell save the information into a file or print the directory or ... Such that the parent at least can use it to change directories if the parent wants to.
Wes Hardaker explained the reasoning behind why executing that script does not cause it to change the directory of the parent shell. In order to work around that type of issue, you must "souce" the script instead of execute it. This causes the commands in the script to run in the current shell, rather than a child process.
. ./settings.sh
The first "." is a command which tells the shell to "source" the specified file. Here is the documentation from help .
:
.: . filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.