我创建了带有目录绝对路径的符号链接(Blink),并具有以下示例树:
$ ls -l /tmp/A
total 0
lrwxrwxrwx 1 root root 6 Apr 3 12:27 Blink -> /tmp/B
-rw-r--r-- 1 root root 0 Apr 3 12:27 foo
$ ls -l /tmp/B
total 0
-rw-r--r-- 1 root root 0 Apr 3 12:27 bar
然后我转到 /tmp/A 并将目录更改为 Blink:
$ cd /tmp/A
$ pwd
/tmp/A
$ cd Blink
$ pwd
/tmp/A/Blink
cd ..
返回我,/tmp/A
但如果我输入,例如ls ../foo
我会收到错误:
ls: ../foo: No such file or directory
内置 cd 命令根据需要解析路径,但外部 ls 将 .. 视为 /tmp/B 的上层,因此无法找到 foo。
这里有什么问题?我可以通过相对路径(如 ../foo)从 /tmp/A/Blink 获取 foo 文件吗?
答案1
shell 将当前工作目录存储在$PWD
.这就是 shell 内置命令cd
和的用途pwd
,并且它将符号链接视为普通目录,如您所见。有时这很有帮助,有时则没有。
您可以使用以下方式找到真实目录pwd
(键入help pwd
以获取更多详细信息):
$ pwd
/tmp/A/Blink
$ pwd -L
/tmp/A/Blink
$ pwd -P
/tmp/B
同样,cd
有一个选项-P
(同样,help cd
是你的朋友):
$ cd /tmp/A/Blink
$ pwd
/tmp/A/Blink
$ cd -P ..
$ pwd -P
/tmp
最后,您可以完全关闭该“功能”:
$ set -P
$ cd /tmp/A/Blink
$ pwd
/tmp/B
答案2
我认为您无法做到这一点。如今的 Shell 会跟踪它们如何到达当前位置,它们会按名称跟踪当前工作目录,而不是仅仅依靠文件系统和操作系统来保存它。这意味着内置程序可以cd
“备份”符号链接,而不仅仅是直接跟踪“..”链。
但是当您运行时ls ../foo
,ls
并不知道 shell 通过符号链接到达了目录。 将在“../foo”上ls
执行操作。 stat()
“..”部分来自当前目录,其父目录只有一个“..”条目。整个符号链接并没有改变目录具有单个“.”的方式。和一个“..”条目。符号链接让内核在文件路径中插入额外的间接层。当您将“../whatever”传递给open()
或 时stat()
,内核仅使用执行调用的进程的当前工作目录来确定哪个目录由“..”命名。
答案3
Bruce 和 ams 给出了漂亮的答案,解释了背后的行为。但要真正做到ls ../foo
你所要求的,你可以选择类似的东西
ls $(dirname $PWD)/foo
答案4
你做不到,因为/tmp/A/Blink
是实际上/tmp/B
。所以,ls ../A/foo
确实有效。
相反,您可能会发现能够光盘到真实的 /tmp/B
目录,而不是别名/tmp/A/Blink
.为此,您可以使用以下函数代替cd
(您可以将其放入 .bashrc 中)
lcd() { cd $(readlink -f "$1"); }
lcd
当然,适用于普通目录和符号链接目录。
注意:readlink -f
作用于链接的最终目标(当链接是菊花链时)。