The commands cd
and pwd
have two operational modes.
The important thing to know here is that cd ..
does not call the syscall chdir("..")
but rather shortens the $PWD
variable of the shell and then chdirs to that absolute path.
If you are in physical mode, this is identical to calling chdir("..")
, but when in logical mode, this is different.
The main problem here: POSIX decided to use the less safe logical mode as default.
If you call cd -P
instead of just cd
, then after a chdir()
operation, the return value from getcwd()
is put into the shell variable $PWD
and a following cd ..
will get you to the directory that is physically above the current directory.
So why is the POSIX default less secure?
If you crossed a symlink in POSIX default mode and do the following:
ls ../*.c
cd ..
rm *.c
you will probably remove different files than those that have been listed by the ls
command before.
If you like the safer physical mode, set up the following aliases:
alias cd='cd -P'
alias pwd='pwd -P'
Since when using more than one option from -L
and -P
the last option wins, you still may be able to get the other behavior.
Historical background:
The Bourne Shell and ksh88 did get directory tracking code at the same time.
The Bourne Shell did get the safer physical behavior while ksh88 at the same time did get the less safe logical mode as default and the options -L
and -P
. It may be that ksh88 used the csh behavior as reference.
POSIX took the ksh88 behavior without discussing whether this is a good decision.
BTW: some shells are unable to keep track of $PWD
values that are longer than PATH_MAX
and drive you crazy when you chdir into a directory with an absolute path longer than PATH_MAX
. dash
is such a defective shell.