Shell Change to different dir at script finish?

OK. This should be dead simple. But I'm somehow finding it strangely difficult.
~ # _
#/bin/sh -

do stuff
cd /tmp

~ # _
Hmm... still in home directory. So what gives. I know it's something so obvious it's alluding me. But for the life of me. I can't figure out why I can't end a script changing into another dir, and end up there when it exits.


That cd /tmp is changing the directory for the shell process running the script, which is a child process of the interactive shell you launched it from. This is by design; think of the additional complications (and security implications) of having a child process change the parent's working directory without warning.

You could set up an alias to call your script and then the cd. See the man page of your interactive shell for directions.
If you come from a background of different (non-Unix) operating systems, such as VM/CMS on mainframes, and VMS on minicomputers, these sorts of questions can be very vexing. Why can't I write a program that changes my environment variables? Why can't I write a program that changes my current directory? When I say "program" here, that could include shell scripts (which are in reality just programs which are executed in a different fashion, just like python, awk and java programs are executed in different fashions).

The answer is, as given above, that in the Unix philosophy every command that is executed, every program that is run, is in a separate process, which is started as a child process. And clearly a child process can not change the environment of the parent process, which in your case happens to be the shell. After all, the shell is in reality just a completely normal user program, which isn't special in any way (other than this it used more than any other program, and is the first one that starts after you login).

In VMS, this is different. There the shell IS different: It runs at a privilege level that is neither the kernel (extremely high privileges), nor a user program (no privileges), but something in between. And the shell doesn't start new processes to run programs ... that is way too expensive (remember, VMS was designed as an industrial-strength multiuser operating system at the time when 1 MIPS had to serve dozen of users, while at the same time Unix was a research experiment whose performance was not really relevant). So the way the interface between shell and program works is that the shell executes the program in its own address space, after carefully dropping its privileges, and gathering them back when the user program exits. For that reason, there are system calls that allow a child program to change the moral equivalent of environment variables (in VMS I think they were called "logical names"), including the current directory.

Could such a thing be added to Unixes? Absolutely. After all, each process (including a user program) knows which process group it is in, and knows the identity of its parent process. It would be perfectly possible to write a system call that allows one process to change the environment of other processes, and design a authorization system that can decide whether such a change shall be allowed or not. It would require a little bit of rework on all shells, not a big deal (compared to major efforts, like systemd). Even though this is doable, nobody would or should try it, because it is not "the Unix way". It would be unethical (because it would cause Dennis to spin in his grave), and dangerous (Ken might actually come after us with a stick, he lives less than 20 miles from me).

Sometimes these things can be best understood this way: Please listen to Zero Mostel singing "Tradition", the opening song of "Fiddler on the roof".
Heh. My problem is all too often; that when I'm in a hurry, and get frustrated because something I am sure should work, but isn't. I nearly always grab the microscope. When I usually need the macroscope.
Thanks for such a wonderful elaboration on the topic, ralphbsz ! It made for a really great story!