Does $PWD always equal $(realpath .)

2019-07-04 04:47发布

Given

  • A modern Linux/UNIX/OSX (w/ realpath)
  • bash 4+ (even on OSX)

Is

"$PWD" == "$(realpath .)"

Always true?

标签: linux bash shell
2条回答
爷的心禁止访问
2楼-- · 2019-07-04 04:59

It is not necessarily the case even when symbolic links are not used and PWD is not set by the user:

vinc17@xvii:~$ mkdir my_dir
vinc17@xvii:~$ cd my_dir
vinc17@xvii:~/my_dir$ rmdir ../my_dir
vinc17@xvii:~/my_dir$ echo $PWD
/home/vinc17/my_dir
vinc17@xvii:~/my_dir$ realpath .
.: No such file or directory

Note that under zsh, ${${:-.}:A} still gives the same answer as $PWD (the zshexpn(1) man page says about the A modifier: "Note that the transformation takes place even if the file or any intervening directories do not exist.").

Note that however, $PWD contains obsolete information. Using it may be a bad idea if some other process can remove the directory. Consider the following script:

rm -rf my_dir
mkdir my_dir
cd my_dir
echo 1 > file
cat $PWD/file
rm -r ../my_dir
mkdir ../my_dir
echo 2 > ../my_dir/file
cat ./file
cat $PWD/file
rm -r ../my_dir

It will output:

1
cat: ./file: No such file or directory
2

i.e. $PWD/file has changed.

查看更多
仙女界的扛把子
3楼-- · 2019-07-04 05:11

It's pretty easy to test that this is not always the case.

$ mkdir /tmp/realdir
$ cd /tmp/realdir
$ echo $PWD
/tmp/realdir
$ ln -s realdir /tmp/fakedir
$ cd /tmp/fakedir
$ echo $PWD
/tmp/fakedir
$ realpath .
/tmp/realdir

so no, $PWD is not always the same as $(realpath .).

The bash manual indicates that the PWD variable is set by the built-in cd command. the default behaviour of cd is:

symbolic links are followed by default or with the -L option

This means that if you cd into a symlink the variable gets resolved relative to the symlink, not relative to the physical path. You can change this behavior for a cd command by using the -P option. This will cause it to report the physical directory in the PWD variable:

$ cd -P /tmp/fakedir
$ echo $PWD
/tmp/realdir

You can change the default behavior of bash using the -P option:

$ set -P
$ cd /tmp/fakedir
$ echo $PWD
/tmp/realdir
$ set +P
$ cd /tmp/fakedir
$ echo $PWD
/tmp/fakedir

This is of course notwithstanding the fact that you can assign anything you want to the PWD variable after performing a cd and it takes that value:

$ cd /tmp/fakedir
$ PWD=/i/love/cake
$ echo $PWD
/i/love/cake

but that's not really what you were asking.

查看更多
登录 后发表回答