考虑以下设置:
~/Desktop/Public/subdir
~/Desktop/subdir --> ~/Desktop/Public/subdir (symbolic link)
现在我这样做:
cd ~/Desktop/subdir
这引导我进入链接目录。
如果我现在发出命令:
cd ..
我将被移回到Desktop
目录中。这意味着 cd 命令是上下文相关的 - 它会记住我是subdir
通过符号链接输入的。
但是,发出命令
cp testfile ..
将复制testfile
到Desktop/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 -P
bash 或setopt chase_links
zsh将其关闭。
该命令pwd
显示 shell 跟踪的当前目录。像 一样cd
,您可以通过选项-L
或-P
来强制逻辑或物理跟踪。
所有这一切都发生在外壳内。诸如此类的外部应用程序cp
无法知道跟踪 shell 内部正在做什么。因此,如果您想在命令的参数中使用逻辑目录跟踪,则需要首先将其转换为不依赖于逻辑跟踪的路径。
shell 变量PWD
跟踪当前目录($PWD
包含与打印相同的字符串pwd
)。如果您想删除当前目录的跟踪路径的最后一个文本组件,而不是附加/..
仅适用于逻辑跟踪的内容,则可以使用文本方法。
cp testfile "${PWD##*/}"
或者在 zsh 中:
cp testfile $PWD:h
如果您想要键入..
且不必考虑以不同的方式表达目录,请运行cd
到所需的目标目录,然后在命令的参数中使用目标的路径。
cp testfile "$(cd .. && pwd)"