Is it mainly because pwd
is not a builtin, while .
is builtin to the bash shell?
For example, they differ in the following example:
/tmp/ttt$ mv ../ttt ../tttt
/tmp/ttt$ pwd
/tmp/ttt
/tmp/ttt$ cd .
/tmp/tttt$
.
is not a bash (or any other shell) built-in. Each and every directory has entries .
and ..
in it. You can verify by cd'ing to some arbitrary directory and doing ls -lia
. You will see .
and ..
entries. I had you use the '-i' flag on ls
to get inode numbers: note them for .
and ..
. Go up a directory, but doing cd ..
or cd /something/soemthingelse/whatever
. Do ls -lia
again. Notice that the inode number of .
is identical to that of ..
in your first listing. Every directory has directories in it when created, named "." and "..". The "." entry has the same inode number as the directory's name does in its parent directory. The ".." entry is always the parent directory. If you do ls -li /
you will see that "." and ".." have the same value.
This convention eliminates the need for special case code to reference the current directory: it's always named ".". It eliminates the need for special case code to "go up one directory": it's always "..". The only special cases are the root directory, and network-mounted filesystems. The filesystem root has "." and ".." with the same inode number, not different. Network-mounted filesystems have a discontinuity in inode numbers at the mount point, and behavior depends on what the remote filesystem is, and what protocol is used to mount it.
As far as the change in prompt, when you invoked mv ../ttt ../tttt
, you actually renamed your shell's working directory. You didn't invoke a shell command that checks working directory until you did cd .
, so the intervening pwd
reports the old name, /tmp/tt
.
cd .
cause my shell prompt to change?"
Commented
Oct 3, 2015 at 14:40
Assuming you're using Bash which has pwd
as a builtin1, what happens is that the cd
command triggers the shell to update the information regarding the current directory. Until you run cd
, the shell will think that the current directory hasn't changed, so it doesn't try to get its new path.
By the way, to expand a bit on Gnouc's answer, the Open Group Base Specifications Issue 6 on environment variables says:
PWD
[...] shall represent an absolute pathname of the current working directory. It shall not contain any filename components of dot or dot-dot. The value is set by thecd
utility.
On the other hand, if you'll run the external /bin/pwd
command, you'll get the new name of the current directory. Why does this happen? The pwd
command from coreutils does some sanity checks of the PWD
environment variable and doesn't print it if it's invalid. The details can be found
in the source code of the logical_getcwd
function (from coreutils version 8.23).
Another command you can use to the get the cannonical path of the current directory is readlink -f .
2.
[ciupicri@host ttt]$ pwd
/tmp/ttt
[ciupicri@host ttt]$ mv ../ttt ../tttt
[ciupicri@host ttt]$ pwd
/tmp/ttt
[ciupicri@host ttt]$ /bin/pwd
/tmp/tttt
[ciupicri@host ttt]$ readlink -f .
/tmp/tttt
1 Running type pwd
can confirm this.
2 From the readlink man page: -f
, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist.
mv
doesn't make the shell to update its current directoty info. .
is a special subdirectory pointing to the directory itself which means that cd .
changes to the same directory.
Commented
Jul 31, 2014 at 17:03
pwd -P
(Physical) will report the correct directory, even if it is a shell builtin (tested inside bash). And, after pwd -P
reports the correct value, the memory value gets updated and plain pwd
will reort it correctly also.
pwd
will print the value of $PWD
if it contains an absolute pathname that does not have dot .
or dot-dot ..
. From POSIX pwd definition:
-L
If the PWD environment variable contains an absolute pathname of the
current directory that does not contain the filenames dot or dot-dot,
pwd shall write this pathname to standard output. Otherwise, if the PWD
environment variable contains a pathname of the current directory that
is longer than {PATH_MAX} bytes including the terminating null, and the
pathname does not contain any components that are dot or dot-dot, it is
unspecified whether pwd writes this pathname to standard output or
behaves as if the -P option had been specified. Otherwise, the -L option
shall behave as the -P option.
By default, pwd
use -L
option so it will print value of current PWD
, which is set when you use cd
. When you mv
the current directory to new path, PWD
still not change, so you will get the old pathname.
You can have some ways to get the right new pathname:
-P
option: pwd -P
/proc
: ls -l /proc/self/cwd
Note
As POSIX definition for variable PWD, if an application set or unset value of PWD
, the behaviors of the cd
and pwd
are unspecified.
% cuonglm at /tmp/ttt
% PWD=/home/cuonglm
% cuonglm at ~
% pwd
/tmp/ttt
% cuonglm at ~
% pwd -P
/tmp/ttt
pwd -P
, running the external command can be good enough, i.e. /bin/pwd
will print the new directory name.
Commented
Jul 31, 2014 at 17:11
/bin/pwd
use -P
option by default if POSIXLY_CORRECT
isn't set. This is just my habit when use pwd -P
.
POSIXLY_CORRECT=1 /bin/pwd
or env POSIXLY_CORRECT=1 pwd
makes no difference. The new directory is still printed.
Commented
Jul 31, 2014 at 17:20
pwd
command depends on the environment variable named POSIXLY_CORRECT
.
Commented
Jul 31, 2014 at 17:39
pwd
can be a builtin.type pwd
returnspwd is a shell builtin
under bash-4.2.47-3.fc20.x86_64..
is a directory. The shell.
builtin is a synonym ofsource
command and is not what you are seeing in this question.