如何使用 cp 以幂等方式递归复制文件夹?

如何使用 cp 以幂等方式递归复制文件夹?

当我使用

cp -R inputFolder outputFolder

结果是依赖于上下文的:

  1. 如果outputFolder不存在则创建,克隆的文件夹路径为outputFolder.
  2. 如果outputFolder存在,那么创建的克隆将是outputFolder/inputFolder

这太可怕了,因为我想创建一些安装脚本,如果用户错误地运行它两次,他将outputFolder创建第一次,然后在第二次运行时,所有内容将在 中再次创建outputFolder/inputFolder

  • 我总是想要第一个行为:在原始对象旁边创建一个克隆(作为兄弟)。
  • 我想用的cp是便携式的(例如MINGW没有rsync发货)
  • 我检查过cp -R --parents,但这会重新创建目录树上的路径(因此克隆不会是outputFolder但是some/path/outputFolder
  • --remove-destination或者--update如果情况 2 不改变任何内容,仍然会将内容复制到outputFolder/inputFolder

有没有办法在不首先检查是否存在outputFolder(如果文件夹不存在则...)或使用的情况下执行此操作rm -rf outputFolder

达成一致的、可移植的 UNIX 方法是什么?

答案1

使用这个代替:

cp -R inputFolder/. outputFolder

其工作方式与工作方式完全相同cp -R aaa/bbb ccc:如果ccc不存在,则将其创建为其bbb内容的副本;但如果ccc已经存在,则将ccc/bbb创建为其bbb内容的副本。

对于几乎任何bbb这种情况,都会产生您在问题中指出的不良行为。然而,在这种特定情况下,“bbb只是” ., “aaa/bbb真的”也是如此aaa/.,而“真的”又是“真的只是” aaa,但有另一个名字。所以我们有这两种情况:

  1. ccc不存在:

    该命令的cp -R aaa/. ccc意思是“创建并复制intoccc的内容,即复制到.aaa/.ccc/.aaaccc

  2. ccc确实存在:

    该命令的cp -R aaa/. ccc意思是“将内容复制aaa/.ccc/.,即复制aaaccc

答案2

不要复制文件夹,只复制内容:

## Create the target directory. The -p suppresses error messages
## if the directory already exists
mkdir -p outputFolder

## Copy the contents recursively, this will not recreate the parent
cp -R inputfolder/* outputfolder/

这样,您既可以确保在脚本第一次运行时创建目标目录,又可以避免第二次运行时出现问题。

Chris Down 非常正确地指出,在 bash 中,这将跳过名称以..为了避免这种情况,您可以shopt -s dotglob在运行上述命令之前运行。

两个都-p为了mkdir-R为了cp由 POSIX 定义,因此应该是完全可移植的。

答案3

尝试-T选择cp.这存在于 GNU coreutilscp版本 8.22 中;在此之外它可能无法移植。

答案4

您可以使用命令-t选项cp

cp -R inputFolder -t outputFolder

现在,如果目标文件夹不存在,则会抛出错误:

cp: failed to access ‘outputFolder’: No such file or directory

注意上面的命令将inputFolder连同其内容一起复制(而不仅仅是其中的内容)

如果你只想复制inputFolder它的内容会有点棘手(因为在使用星号 * 时使用 shell 通配符时必须小心)

cp -R  -t outputFolder/ -- inputFolder/*

现在,如果目标文件夹不存在,则会抛出错误:

cp: failed to access ‘outputFolder’: No such file or directory

cp (GNU coreutils) 8.23

相关内容