当我位于符号链接文件夹内时从父位置复制文件

当我位于符号链接文件夹内时从父位置复制文件

/tmp假设我在Calledparent和中创建了两个文件夹childchild包含一个名为 的文件test-child.txt,并parent包含一个名为 的文件test-parent.txt。现在让我们进入parent并创建一个到 的符号链接child。接下来,进入child并尝试test-parent.txt从复制parent。 bash 完成工作正常,但实际文件复制失败 --

cd /tmp
pwd
/tmp
mkdir parent
mkdir child
touch child/test-child.txt
ls child/
test-child.txt
cd parent
ln -sf ../child .
touch test-parent.txt
cd child
cp ../test-parent.txt .
cp: cannot stat ‘../test-parent.txt’: No such file or directory 

为什么 ??

而且,当我在里面时child,如果我说——

pwd
/tmp/parent/child

答案1

Shell 会跟踪符号链接以方便用户。这具有cd foo && cd ..始终返回到原始目录的良好效果,即使foo是指向目录的符号链接也是如此。它有两个缺点:主要的​​一个是其他程序不这样做;另一个缺点是其他程序不这样做。此外,符号目录跟踪引入了其自身的问题(当符号链接更改时会发生什么?如果进程没有读取符号链接的权限会发生什么?等等)。

Shell 只能做到这一点,因为它们会跟踪所有目录更改,因此它们会记住您是如何到达那里的。当新进程启动时,它不会获取此历史信息。在幕后,它通过从当前目录向上移动、跟踪..链接直到到达根目录来找到它所在的位置。

如果您通过符号链接到达目录,则可以使用以下命令打印出无符号链接的路径pwd内置的,通过调用pwd -P.如果您从 shell 调用另一个程序,请勿向其传递包含..符号链接组件的路径,因为该程序会对它进行不同的解释。相反,..通过调用消除组件pwd -P

cp "$(cd .. && pwd -P && echo /)test-parent.txt" .

如果您想忘记cdshell 会话中过去命令中使用的符号链接,您可以运行

cd "$(pwd -P && echo /.)"

这会更改为当前目录,因此它不会有效地更改 shell 进程的当前目录,但会更改 shell 跟踪的当前目录的路径,使其成为无符号链接。

1这就是getcwd呼叫的传统运作方式。某些内核确实会跟踪当前目录,但不跟踪符号链接,如果没有其他原因,则为了向后兼容(但也因为符号链接的微妙边缘情况)。

答案2

这是因为cp你的 shell 玩的不是同一个链接游戏。您的 shell 正在跟踪当前工作目录的链接,作为当前工作目录的间接访问,但是当 shell 调用时,内核不希望出现任何废话cp- 相反,内核将创建 的cp当前工作目录一个完全限定的绝对路径 - 因此它的.链接和你的 shell 的.链接是不一样的.

您可以轻松确保当前工作目录的绝对路径,cd -P .并且同样适用于任何其他目录,例如cd -P -- /any/other/directory.你可以至少用于打印likepwd的绝对路径,并且在许多 shell 中它也会更改为绝对路径.pwd -P$PWD(以同样的方式cd -P .

例如:

cd /tmp
mkdir -p parent child
cd parent
ln -s ../child child
touch ./child/somefile
cd -L child                  ###the default
printf %s\\n "$PWD"/*
cd -P .
printf %s\\n "$PWD"/*

输出

/tmp/parent/child/somefile
/tmp/child/somefile

相关内容