在 OS X 上,递归 cp 复制文件夹内容而不是文件夹

在 OS X 上,递归 cp 复制文件夹内容而不是文件夹

在终端(使用 bash 和 tcsh)中,如果文件夹参数末尾有 /,则 cp -r 将复制文件夹的内容而不是文件夹本身。

鉴于以下结构:

folderA
  |-fileA
  |-fileB

以下命令将文件 A 和文件 B 复制到目标,而不是将文件夹 A 复制到目标:

cp -r folderA/ destination

因此它充当

cp -r folderA/* destination

这非常烦人,因为默认情况下 tcsh 中的补全会在文件夹末尾添加一个 /,所以如果我忘记删除末尾的 /,我总是不得不清理。这种行为与我使用过的其他 *nix 不同。

有什么方法可以改变这种情况并让 cp -r folderA/ 复制文件夹而不是其内容?

答案1

有案例表明这种行为更有意义(我相信 rsync 也使用它,即使在 GNU/Linux 上也是如此)。考虑以下情况:

 mydir
   |-.fileA
   |-fileB

这三个说明符的语义都是不同的:

 cp -r mydir   dest/   # creates dest/mydir, containing both files
 cp -r mydir/  dest/   # copies both files directly into dest
 cp -r mydir/* dest/   # copies fileB, but not .fileA, directly into dest

我相信这是 BSD 和 GNU 之间差异的一个例子。您可以使用以下方式安装 GNU 风格的工具芬克(看coreutils 包),但这些可能无法保留所有 HFS+ 元数据,因此请谨慎操作。

您可以截取命令并删除末尾的斜线。我将把这个留给读者或其他回答者作为练习。

您可以更改制表符补全行为,这样就不会首先添加斜线。将以下内容添加到您的~/.tcshrc

 unset addsuffix

你可以在 bash 和其他 readline 实用程序中通过将以下内容添加到你的 来实现类似的效果~/.inputrc

 set mark-directories off

答案2

无需手动删除默认安装中附加的“/”?不幸的是,苹果的 Darwin 上没有说明手册页cp 的意思是“如果源文件以 / 结尾,则复制目录的内容,而不是目录本身。”所以看起来这是达尔文设计的一部分cp

但是,可以取消设置addsuffixshell 变量,tcsh以便删除添加到目录中的“/”。最大的缺点是,现在很难仅从完成中判断您正在处理的是目录还是文件。为此,请在命令行中键入(或添加到 .tcshrc):

 unset addsuffix

bash可以使用该mark-directories设置。你可以输入以下内容或将其添加到你的 .bashrc 中:

 bind 'set mark-directories off'

标记目录的使用来源:MacNN 论坛:Hal Itosis

答案3

“您可以拦截命令并删除尾部的斜杠。我将把这个留给读者或其他回答者作为练习。”添加

function cp() { /bin/cp $(echo "$*" | sed 's|/ | |g'); }

到 ~/.bashrc 似乎可以解决问题。

相关内容