tags:

views:

77

answers:

2

When I created my own shell, I am not able to execute cd command which I am able to do in the Linux shell. Why is that?

+4  A: 

That's probably because the cd command has to be built into the shell, not something external and executed. If an external command changed directory, it has no effect on the parent shell. And there is no command /bin/cd or /usr/bin/cd.


I do not understand the line "If the external command changed directory, it has no effect on the parent shell".

Normally, when a shell executes a command, it does fork() and the child process uses exec() to execute the command entered by the user. For example, if the entered command is 'ls /', the shell arranges to execute /bin/ls with two arguments, ls and /. However, if the command selected executes the chdir() system call, that affects the child process, but does not affect the parent shell. So, the shell has to handle the cd command itself, not via fork() and exec().

Note that in DOS, a .BAT file can do cd and it affects the cmd.exe process. This does not happen in Unix - a child process cannot affect the current directory of the parent process.

Jonathan Leffler
thanks for the answer but I did not understand the line "If the external command changed directory, it has no effect on the parent shell".
phani987
Unix/Linux and DOS are the same in that each process has its own current directory. The difference is that in DOS, BAT files (and nested BAT files) are run by the current cmd.exe process whereas in Unix/Linux, running a shell-script starts a new shell process. In Unix/Linux, if you run CD inside a script, it changes that shell's current directory which will affect later commands in the same script. But the shell that started the script is not affected.
Adrian Pronk
@Adrian: you're correct - I wondered whether to leave that last paragraph in, or whether it would confuse the OP. Your explanation is clearer than mine.
Jonathan Leffler
+2  A: 

Jonathan Leffler explained why this was, but I wanted to offer a workaround in case you actually need this functionality. In bash (you didn't specify, so I'll assume), the source command can be used to execute a shell script in the CURRENT shell process. I use something similar to the below (though more comprehensive), along with a shell alias, to change to project directories and automagically set up the environment:

~:$ cat $HOME/bin/goproj
#!/bin/bash
...
export SOMEVAR=someval
cd /home/foo/src/projects/"$1"
...

~:$ alias gp
alias gp="source $HOME/bin/goproj"

~:$ gp foo
~/src/projects/foo:$ echo $SOMEVAR
someval
~/src/projects/foo:$

Using this type of setup, you can modify the current shell with whatever exists in the script you're sourcing. Note that if you ran 'goproj' directly, it wouldn't work for the same problem you're already experiencing; you must call it with source.

Simon
And now that I reread the question, this was probably silly to type up :-) Oh well.
Simon
+1: This is useful when the shell has implemented the `cd` command internally (and also the `source` or `.` command). AFAICT, the question is about a home-brew shell that does not implement `cd` (via the `chdir()` system call), and therefore no amount of sourcing will help change directory until it does.
Jonathan Leffler
Yep, I gleaned that on my mental parser's second pass.
Simon