Ubuntu – Why wouldn’t the `which` command work for `cd`? I can’t find the executable for `cd` either!

command linecoreutils

I tried which cd and it didn't give a path but instead returned the exit code 1 (checked with echo $?). The coreutil cd itself is working, so the executable should be there, right? I also ran a find for cd, but there was no executable file shown. How is it implemented then?


I don't know if I should ask this in another post but since I think it is good here, I'm expanding (?) the post… So the answer was actually quite simple, there's no executable for that — because it's a builtin — But I've found some builtins (bash shell in Fedora) have the executable files! So builtin -> no executable isn't right I suppose? Maybe an answer explaining what builtins actually are (builtin commands?), which actually is the matter here, rather than focusing more on cd… Some good links posted previously indicate that builtins are not programs… so what are they? How do they work? Are they just functions or threads of the shell?

Best Answer

Command cd can not be an executable

In a shell, cd is used to "go into another directory", or more formally, to change the current working directory (CWD). It's impossible to implement that as an external command:

The directory belongs to a process

The current working directory is the directory that is used to interpret relative paths to obtain a full path that can be used to access files.
Relative paths are used in many places, and the interpretation in one process should not influence another process.
For this reason, every process has its own current working directory.

cd is about changing the current working directory of the shell process, for example, bash.

If it were an external command, an executable in the path, running that executable would create a process with its own working directory, without influencing that of the current shell. Even if the external command would change its directory, that change goes away when the external process exits.

Shell builtin commands

So it makes no sense to run an external command for the task of cd. The command cd needs to apply a change to the currently running shell process.

To do that, it is a “builtin command” of the shell.

Builtin commands are commands that behave similar to external commands, but are implemented in the shell (so cd is not part of the coreutils). This allows the command to change the state of the shell itself, in this case, to call chdir() see (see man 2 chdir);

About which

Now, the answer to the title question is easy:
The executable command which can not tell us that cd is a builtin command because an executable command does not know anything about builtins.

Alternative type -a

As an alternative to which, you can use type -a; It can see executable commands and builtins; Additionally, it sees aliases and functions - also implemented in the shell:

$ type -a cd
cd is a shell builtin
$ type -a type
type is a shell builtin
$ type -a which
which is /usr/bin/which
which is /bin/which