use*_*976 17 shell symlink pwd
我添加了一个符号链接到当前目录ln -s . aa。如果我执行cd aa,然后我执行pwd,响应是/home/sim/aa。
但是如果我执行/bin/pwd它会打印/home/sim(当前目录没有改变)。
这种差异从何而来?
cuo*_*glm 17
在包括 bash 在内的大多数 shell 中,pwd是一个内置的 shell:
$ type -a pwd
pwd is a shell builtin
pwd is /bin/pwd
Run Code Online (Sandbox Code Playgroud)
如果使用/bin/pwd,则必须使用-L选项来获得与 builtin 相同的结果pwd:
$ ln -s . test
$ cd test && pwd
/home/cuonglm/test
$ /bin/pwd
/home/cuonglm
$ /bin/pwd -L
/home/cuonglm/test
Run Code Online (Sandbox Code Playgroud)
默认情况下,/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.
Run Code Online (Sandbox Code Playgroud)
内置pwd默认包含符号链接,除非使用该-P选项,或者-o physical启用了 set builtin。
来自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.
Run Code Online (Sandbox Code Playgroud)
进程可能会询问文件系统以确定其当前工作目录,使用的方法有点过于复杂,无法作为这个问题的答案。这就是pwd程序和getcwd库函数所做的。在 Unix 的早期,它们是找出您的工作目录的唯一方法。以下是我在其他任何答案中都找不到的问题的部分答案,甚至在本网站的其他任何地方都找不到(经过 42 秒的搜索):
getcwd)。此后,无论何时执行 a cd、pushd或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的记忆/计算的工作目录是什么概念。因此,底线是外壳可能会混淆它的位置。但是,如果您键入/bin/pwd,它将在一个单独的进程中运行,该进程无权访问 shell 的工作目录概念,因此它确定了真正的工作目录本身,这是老式的方式。(例外:/bin/pwd程序可以查看 PWD 环境变量,显然当您指定-L.时它会查看。)这是外壳如何混淆的另一个示例:
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 . aa和cd aa,那么您当前的工作目录并没有改变,就像您输入时一样cd .——因为,这本质上就是您在输入时所做的cd aa。