5 ms·
Why is impossible? Maybe I've understood why it is always built in: without it the shell wouldn't be able to navigate through the directory tree to find the exe
by GTP 11y ago
Why is impossible? Maybe I've understood why it is always built in: without it the shell wouldn't be able to navigate through the directory tree to find the executables of the commands. But once the shell has it, I think it would be rendundant (so nobody does it) but still possible to have a /bin/cd that navigates directories.
- duaneb 11y agoYou can't change the environment of the parent process, including CWD. `/bin/cd` would either be another process like all executables run by the shell, and not work, or special cased, at which point why make it an executable at all?
- schoen 11y agoThe parent comment's explanation is exactly right (although I might not use "CWD" in this context, because a reader might mistakenly think the working directory is determined by an environment variable). As an example, try python -c 'import os; os.chdir("/")' Notice that the working directory of your shell is unaffected. :-) Or: bash -c 'export foo=bar'; echo $foo
- Someone1234 11y agoThose examples are trying to change the directory on the shell's child process, not on the shell itself. That being said, aside from a kernel patch there is definitely no official way of doing it. This is the hacky way: http://stackoverflow.com/questions/2375003/how-do-i-set-the-working-directory-of-the-parent-process http://stackoverflow.com/questions/2375003/how-do-i-set-the-...
- schoen 11y agoI meant for my examples just to illustrate that a child process can't change the working directory or environment of the parent process.
- JoshTriplett 11y agoI can think of one way to write "cd" out-of-process from the shell: exec /bin/cd /some/path, which does chdir("/some/path") and execs your shell. You'd lose your history and similar state, but if you had a shell that didn't even put cd in-process, it probably doesn't have history either. Sample: /tmp$ exec /tmp/cd /bin /bin$ exec /tmp/cd /home /home$ exec /tmp/cd /usr /usr$ Sample code: #include <err.h> #include <stdlib.h> #include <unistd.h> int main(int argc, char *argv[]) { char *shell; if (argc != 2) errx(1, "Usage: exec cd /some/path"); if (chdir(argv[1]) == -1) err(1, "chdir"); shell = getenv("SHELL"); if (!shell || !*shell) shell = "/bin/sh"; execl(shell, shell, NULL); err(1, "exec"); }
- duaneb 11y agoHah, hadn't thought of that. Kind of CPS for processes. I'm not sure what that would gain you, though, as you'd have to either a) write both the cd and the user of the cd, and there are less awkward ways to do that than exec'ing, or b) you'd have to pass something ELSE to exec to return control after cd finishes. This seems a little awkward and I'm not sure what is being proven. :P
- aardvark179 11y agoIt's how very early version of Unix effectively did stuff, they exceed a program, and when it exited they exceed the shel again. When they introduced something like the fork/exec model we now have they discovered cd didn't work any more and had to write it as a built in. Now, for bonus points, work out how goto worked when it wasn't a built in.
- JoshTriplett 11y ago> It's how very early version of Unix effectively did stuff, they exceed a program, and when it exited they exceed the shel again. Makes sense, since those systems might not have enough memory to run the shell and another program at the same time.
- 11y ago
- rleigh 11y agoIt's impossible because it simply calls chdir(2). The "current directory" is a property of a process; having it built-in means it changes the directory of the current process. If it was a separate executable, you'd change the directory in a separate child process for that executable, and the current directory of the shell would be unchanged, making it entirely useless.