cp SOMEFILE .. 通过符号链接 cd 后复制到不同的目录

cp SOMEFILE .. 通过符号链接 cd 后复制到不同的目录

考虑以下设置:

~/Desktop/Public/subdir
~/Desktop/subdir --> ~/Desktop/Public/subdir (symbolic link)

现在我这样做:

cd ~/Desktop/subdir

这引导我进入链接目录。

如果我现在发出命令:

cd ..

我将被移回到Desktop目录中。这意味着 cd 命令是上下文相关的 - 它会记住我是subdir通过符号链接输入的。

但是,发出命令

cp testfile ..

将复制testfileDesktop/Public.

我更喜欢 的行为而cd不是 的(通常不可预测的)行为cp。无论如何,我想知道这种行为差异的原因是什么?只是一个遗留问题还是有充分的理由?

答案1

之所以cd知道您已通过 a 进入目录,symlink是因为它是内置于 shell 中的。该cp命令是外部二进制文件,仅通过命令行参数和环境变量传递数据。环境变量不包含以下数据如何您进入了当前目录。

如果您使用bash,您可以使cd功能相同,就像cp您希望事情保持一致一样。set -P将实现这一点。从联机帮助页:

          -P      If  set,  the shell does not follow symbolic links when executing commands such as cd that change the current working directory.  It uses the physical directory structure instead.  By default, bash follows the
                  logical chain of directories when performing commands which change the current directory.

答案2

cd按照描述工作时,它只能是cd你的外壳的一个伎俩。..是父目录的条目。在你的情况下, 的父项subdir只能是Public并且不能Desktop。因此,cp如果正确思考,您将通过重定向获得相同的行为(例如>)。

cd 示例仅使用一些“用户友好”技巧来表现得像它一样。看https://stackoverflow.com/questions/10456784/behavior-of-cd-bash-on-symbolic-links

如果您确实需要该功能,则必须使用类似的东西

cp testfile "${PWD##*/}"

(复制到当前目录的父目录,根据shell跟踪)。在 zsh 中,您可以将其简化为cp testfile $PWD:h

答案3

恰恰相反:cp行为与任何其他应用程序一样,它解释..为当前目录的父目录。这是因为内核将其解释..为当前目录的父目录。

当您运行cd符号链接时,您传递到的路径cd不会使目标目录的父目录变得明显。当你运行 时cd ~/Desktop/subdir,目的地不是/home/konstantin/Desktop/subdir——那是一个符号链接。目标目录是/home/konstantin/Desktop/Public/subdir. (或者,迂腐地说:目标目录是根目录subdir的子目录的子目录的子目录Public,...的子目录。)不是:父目录仅在没有子目录的情况下才具有的属性。home/home/konstantin/Desktop/subdir/../home/konstantin/Desktop/…stuff…/subdir/…stuff…

由于将目录的符号链接视为目录通常很方便,因此 shell 执行符号链接跟踪。当您运行时cd,shell 会记住您用来到达目的地的路径(可能使用符号链接)。当您..在 的参数cd(或类似的 shell 内置函数,例如pushd)中使用时,shell 会执行 的文本解释,..而不是将其解释为当前目录:cd /some/stuff/../more转换为cd /some/more。这样,cd其行为就像符号链接实际上是目录一样。

文本解释..称为逻辑目录跟踪,文件系统解释..称为物理目录跟踪。如果您想使用物理目录跟踪(即关闭 的文本解释..),请将该-P选项传递给cd。该-L选项强制逻辑跟踪打开,以防它被禁用。逻辑跟踪默认关闭;您可以使用set -Pbash 或setopt chase_linkszsh将其关闭。

该命令pwd显示 shell 跟踪的当前目录。像 一样cd,您可以通过选项-L-P来强制逻辑或物理跟踪。

所有这一切都发生在外壳内。诸如此类的外部应用程序cp无法知道跟踪 shell 内部正在做什么。因此,如果您想在命令的参数中使用逻辑目录跟踪,则需要首先将其转换为不依赖于逻辑跟踪的路径。

shell 变量PWD跟踪当前目录($PWD包含与打印相同的字符串pwd)。如果您想删除当前目录的跟踪路径的最后一个文本组件,而不是附加/..仅适用于逻辑跟踪的内容,则可以使用文本方法。

cp testfile "${PWD##*/}"

或者在 zsh 中:

cp testfile $PWD:h

如果您想要键入..且不必考虑以不同的方式表达目录,请运行cd到所需的目标目录,然后在命令的参数中使用目标的路径。

cp testfile "$(cd .. && pwd)"

相关内容