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

jak*_*b.g 58 cp recursive

当我使用

cp -R inputFolder outputFolder
Run Code Online (Sandbox Code Playgroud)

结果取决于上下文

  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 方式是什么?

roa*_*ima 71

改用这个:

cp -R inputFolder/. outputFolder
Run Code Online (Sandbox Code Playgroud)

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

对于几乎所有这样的实例,bbb都会出现您在问题中指出的不良行为。但是,在这种特定情况下,bbb只是.aaa/bbb确实是aaa/.,而这实际上只是aaa另一种名称。所以我们有这两个场景:

  1. ccc 不存在:

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

  2. ccc 确实存在:

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

  • 嗯,这对我来说是一个新的,但它似乎确实有效!它记录在任何地方? (4认同)

ter*_*don 20

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

## 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/
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以确保在第一次运行脚本时创建目标目录,并避免在第二次运行时出现问题。

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

无论-pmkdir-R用于cp通过POSIX定义所以这应该是非常便携。

  • 注意:这不会复制以`.` 开头的文件。在 bash 中,你可以使用 `dotglob`。 (8认同)
  • 请注意,如果 inputfolder 中的目录条目数量很大,则此方法可能会失败,因为 glob 扩展可能会超过最大命令行长度。 (4认同)

Tom*_*unt 11

尝试-T选择cp. 这存在于 GNU coreutils cp8.22 版中;除此之外,它可能不可移植。