Your script runs cd /tmp, yet the terminal is still in its original directory after the script exits. cd is working. The question is which shell changed directory.
How do Bash's cd and ls run?
cd is a builtin run by the current shell. The working directory is part of that shell's state, so the same shell must run cd for its later pwd to change. By contrast, Bash normally finds and runs ls as an executable file. Printing a file listing from another process does not change the parent shell's directory.
The diagram separates cd, which changes the current Bash shell's directory, from a typical ls execution, which only produces output. Aliases, functions, and the environment can affect how a command name resolves, so inspect the Bash session you are using.
Use type -t to identify a builtin or file
This example starts Bash without profile or startup configuration. type reports how that shell resolves each name:
bash --noprofile --norc -c 'type -t cd; type -t ls; compgen -b | grep -x cd'builtin
file
cdbuiltin means a command inside Bash; file means an executable found on the search path. compgen -b lists Bash builtins, including cd. To see candidate paths for ls, use type -a ls. Its exact path varies by environment.
Why does cd in a child shell leave the original pwd unchanged?
Start in /tmp, change only the child shell to /, then compare that with a cd in the original shell:
cd /tmp
pwd
bash --noprofile --norc -c 'cd /; pwd'
pwd
cd /
pwd/tmp
/
/tmp
/The middle / is the child's directory. The next /tmp comes from the original shell, which has not moved. Only its own final cd / changes that shell's directory. A child cannot change its parent's working directory in reverse.
The same distinction applies to scripts. A cd inside bash setup.sh affects the shell running setup.sh, not the terminal that launched it. To move your terminal afterward, run cd there. If you want later commands inside a script to use the new directory, keep them in that script's shell, for example cd /tmp && ./run.sh. && prevents the next command from running in the wrong directory when cd fails.
Can which cd print a path even though cd is a builtin?
Yes. which is often used to locate executable files, but an auxiliary executable with the same name may exist, and which itself can be implemented differently across shells. A printed path does not prove Bash ran that file. In the Korean article's independent test environment, type cd reported a builtin while which cd printed /usr/bin/cd.
Use type -a cd to inspect the candidates and type -t cd to see how the current Bash resolves the name first. This also reveals an alias or function if one intervenes. A single which result cannot tell the whole story.
Key takeaways
cd is a Bash builtin that changes the current shell's working directory. A cd in a separate shell moves only that shell. Use type -t to inspect command resolution in your current Bash, and interpret which as a path lookup rather than proof of what Bash executed.

