0

A while ago I wrote a script (let's call it myScript) so that it would cd into a specific folder. I saved it in cygwin home directory so I could run it just by calling ~/myScript. I had problems with it, but got it working by calling

. ~/myScript

I have written a parent script (let's call it parentScript) that does few tasks and wanted to add an option so it would cd to my specific directory by calling myScript inside it.

myScript looks something like this:

cd /cygdrive/c/Users/USER_NAME

parentScript has this:

if [ "${1}" -eq CD_TO_USER_NAME_OPTION ]; then
   . ~/myScript
fi

This gives me the same problem I had before with myScript. It cds in the subshell, but then exits leaving me in the directory I started with. I want to be able to run myScript without using the parent that's why I didn't put in parentScript (like grep -E and Egrep). What am I doing wrong??

Roberto Reale
  • 4,247
  • 1
  • 17
  • 21
alamoot
  • 1,966
  • 7
  • 30
  • 50
  • Unlike DOS and CMD.EXE, a shell script run from the current shell cannot change the directory of the current shell. If you want a script to change the directory of the current shell, you have to `.` (dot) it, or use the Bash C-Shell compatibility extension 'source'. I decline to use C-Shell, so I use `.`. – Jonathan Leffler Apr 18 '14 at 17:59

2 Answers2

1

You would need to invoke parentScript by sourcing it as well:

. parentScript

Then, in whatever script contains that, you would need to make sure the first argument is

./grandparentScript CD_TO_USER_NAME_OPTION

A script invoked by any other means besides sourcing is run in a new process. A process has its own current working directory (man 3 getcwd). That directory is inherited from the parent process, but the parent doesn't get it from the child when the child exits. The only way to have an inner script change the working directory of an outer script is by running them in the same process. That is done most simply by sourcing, or the . command, as you've discovered.

Another solution would be to use a shell function for your directory change:

magicCd() {
    cd my/special/place
}

However, to avoid mixing procedural code with data, maybe the best choice would be simply to use the builtin cd command and store the desired destination in a variable.

my_special_place="$HOME/my/special/place"

cd "$my_special_place"

This last is just as abstract as the sourced script, function or alias, and much more obvious to any maintenance programmer who comes along.

kojiro
  • 74,557
  • 19
  • 143
  • 201
  • This is why `cd` is a shell builtin rather than an external command. – suvayu Apr 19 '14 at 09:08
  • @suvayu actually on POSIX systems [it is both](http://unix.stackexchange.com/questions/50058/what-is-the-point-of-the-cd-external-command) – kojiro Apr 19 '14 at 15:38
  • I'm aware of that, but this external `cd` cannot be used to change directory in an interactive shell or in a script (context of this question). As the accepted answer in the question you point to says, it has other uses just not the usual one users might expect. BTW, thanks for pointing to it. I wasn't aware of all the use cases of an external `cd`. :) – suvayu Apr 20 '14 at 08:49
0

This would be better done via an alias than a shell script:

$ alias myscript="cd /to/some/directory"

Then executing myscript will put you in that directory:

$ myscript
$ pwd
/to/some/directory
David W.
  • 105,218
  • 39
  • 216
  • 337
  • However, aliases are not expanded when the shell is not interactive. If OP runs this within a script, it will fail unless he forces the script to be interactive (a bit ham-fisted, IMO), or makes it a shell function. – kojiro Apr 18 '14 at 17:50
  • Damn, another difference between Kornshell and BASH. In Kornshell, aliases can be exported just like shell variables, and then can be used in scripts. I see `BASH` doesn't do that unless you use `shoot -s expand_aliases` in the script. – David W. Apr 18 '14 at 18:19