Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't the cd command work in my shell program?

Tags:

linux

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?

like image 305
phani987 Avatar asked Sep 18 '10 05:09

phani987


3 Answers

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. (Even though there is usually a command /bin/cd or /usr/bin/cd on Linux and macOS systems, executing it changes the directory for that process, but has no effect on the process that invoked it.)


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.

like image 69
Jonathan Leffler Avatar answered Nov 14 '22 23:11

Jonathan Leffler


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.

like image 43
Sdaz MacSkibbons Avatar answered Nov 14 '22 21:11

Sdaz MacSkibbons


This is as simple as :

  • cd is not a command.

Try this :

-- whereis ls

-- whereis cd

(See the difference)

  • cd is property of the shell, so if you are making a shell then you have to support cd.

See it this way, when ls is executed then it needs to know the pwd. So, it your custom shell that would handle the directory. So, its the shell that has to support cd.

I think I made myself clear.

like image 41
Yugal Jindle Avatar answered Nov 14 '22 23:11

Yugal Jindle