pwd 和 /bin/pwd 之间的奇怪区别

pwd 和 /bin/pwd 之间的奇怪区别

我添加了一个到当前目录的符号链接ln -s . aa。如果我执行cd aa,然后执行pwd,响应是/home/sim/aa.

但是如果我执行/bin/pwd它会打印/home/sim(当前目录没有更改)。

这种差异从何而来?

答案1

在包括 bash 在内的大多数 shell 中,pwd都有一个内置的 shell:

$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd

如果使用/bin/pwd,则必须使用该-L选项才能获得与builtin相同的结果pwd

$ ln -s . test
$ cd test && pwd
/home/cuonglm/test
$ /bin/pwd
/home/cuonglm
$ /bin/pwd -L
/home/cuonglm/test

默认情况下,/bin/pwd忽略符号链接并打印实际目录。

info pwd:

`-L'
`--logical'
     If the contents of the environment variable `PWD' provide an
     absolute name of the current directory with no `.' or `..'
     components, but possibly with symbolic links, then output those
     contents.  Otherwise, fall back to default `-P' handling.

`-P'
`--physical'
     Print a fully resolved name for the current directory.  That is,
     all components of the printed name will be actual directory
     names--none will be symbolic links.

pwd默认情况下,内置包含符号链接,除非-P使用该选项,或者-o physical启用设置内置。

man bash:

pwd [-LP]
              Print the absolute pathname of the  current  working  directory.
              The pathname printed contains no symbolic links if the -P option
              is supplied or the -o physical option to the set builtin command
              is  enabled.  If the -L option is used, the pathname printed may
              contain symbolic links.  The return status is 0 unless an  error
              occurs  while  reading  the  name of the current directory or an
              invalid option is supplied.

答案2

进程可以询问文件系统以确定其当前工作目录,使用的方法有点过于复杂,无法作为该问题的答案。这就是pwd程序和getcwd库函数的作用。在 Unix 的早期,它们是查找工作目录的唯一方法。以下是您的问题的部分答案,我在任何其他答案中都找不到,甚至在本网站的其他任何地方都找不到(经过 42 秒的搜索):

  • 当 shell 启动时,它会获取当前工作目录(可能通过调用getcwd)。
  • 此后,每当您执行cdpushd、 或 时popd,shell跟踪使用字符串操作函数的工作目录。例如,

    • 如果您的工作目录是/home/sim且您键入cd ..,shell 会计算出您的工作目录是/home
    • 如果您的工作目录是/home/sim且您键入cd .,则 shell 会计算出您的工作目录仍然是/home/sim
    • 如果您的工作目录是/home/sim并且您键入cd aa,则 shell 会计算出您的工作目录是/home/sim/aa– 而不检查是否aa是符号链接。

    这样做是为了节省调用的“成本” getcwd。但这是一种权衡,因为它可能会导致错误的信息。

  • (内置)命令pwd只是显示 shell 记住/计算出的工作目录的概念。
  • 此外,shell 将其记住/计算出的工作目录概念放入 PWD 环境变量中,以便方便用户进程。如果一个进程需要准确的信息,那么它永远不应该依赖于此。

因此,最重要的是 shell 可能会对其位置感到困惑。但是,如果您输入/bin/pwd,它将在一个单独的进程中运行,该进程无法访问 shell 的工作目录概念,因此它会以老式的方式确定真正的工作目录本身。 (例外:/bin/pwd程序查看 PWD 环境变量,显然当您指定 时它就会执行此操作-L。)这是 shell 如何混淆的另一个示例:

cd /home/sim/aa #假设/home/home/sim、 和/home/sim/aa
#都是真实目录(不是符号链接)。
pwd #输出:/home/sim/aa,这是正确的。
mv ../aa ../bb
pwd #输出:/home/sim/aa,这是不正确的。
/bin/pwd #输出:/home/sim/bb,这是正确的。


并且,以防万一您对此不清楚,如果您输入ln -s . aaand cd aa,那么您当前的工作目录没有改变,比您键入时所做的更多cd .- 因为,这本质上就是您在键入 时所做的事情cd aa

相关内容