cp、尾部斜杠以及复制到同一目录或复制到另一个目录

cp、尾部斜杠以及复制到同一目录或复制到另一个目录

要将一个目录复制到另一个目录,第一个目录应该不带尾部斜杠:

# example 1
# this command will copy dir1 to dir2
# (dir2 is preexisting)
cp -Rip dir1 dir2/

否则,该命令将复制目录内容而不是目录本身:

# example 2
# this command will copy dir1 contents to dir2
# (dir2 is preexisting)
cp -Rip dir1/ dir2/

dir1我确实理解和这里之间的区别dir1/,并且这两个命令的行为方式之间的区别不会让我感到困惑。

但是,如果要将目录复制到当前所在的同一目录而不是另一个目录,则尾部斜杠不会产生任何区别。为什么?

# example 3
# any of these commands will make a dir1 copy
# (dir1-copy isn't preexisting)
cp -Rip dir1 dir1-copy/
cp -Rip dir1/ dir1-copy/

还有另一个密切相关的问题。为什么howmv dir1/ dir2/mv dir1 dir2/work没有区别?换句话说,为什么源目录末尾的尾部斜杠mv遵循示例三的逻辑cp,而不是示例一和示例二的逻辑?

macOS 14.3.1、zsh 5.9 (x86_64-apple-darwin23.0)

答案1

cp -R dir1 dir2和之间的行为差​​异cp -R dir1/ dir2是 FreeBSD 中添加的一个功能5.4版本。至少,当时在手册中添加了以下句子来描述该-R选项:

如果source_file以 / 结尾,则复制目录的内容而不是目录本身。

这种行为可能比较旧,5.4 只是填补了文档中的一个遗漏。里面没有这方面的内容5.0,5.1,5.2,5.3或者5.4发行说明。我还没有去源码潜水。

现代版本的 FreeBSD 和具有 FreeBSD 命令行实用程序的 macOS 保留了这种行为。其他系统(GNU、BusyBox、OpenBSD、NetBSD 或任何兼容 POSIX 的系统)没有此行为:cp -R dir1/ dir2并且cp -R dir1 dir2具有完全相同的行为(除非dir1是符号链接:dir1/导致链接被跟踪)。

FreeBSD 的行为可能受到 rsync 的启发,它也有同样的区别。我确实觉得很奇怪,他们做了一个向后不兼容的改变,偏离了

但是,如果要将目录复制到当前所在的同一目录而不是另一个目录,则尾部斜杠不会产生任何区别。为什么?

这是一个奇怪的设计决定。或者也许这不是一个设计决策,而是一个实现错误(解析源路径并确定尾部斜杠后面的部分是路径组件),他们决定调用一个功能。使用 rsync,即使目标目录不存在,尾部斜杠也会保持其行为。

mv dir1/ dir2/为什么how和mv dir1 dir2/work没有区别?

不应该有什么区别(假设dir1不是符号链接),所以这只是正常情况。

相关内容