简体   繁体   English

如何强制“cp”覆盖目录而不是在其中创建另一个目录?

[英]How to force 'cp' to overwrite directory instead of creating another one inside?

I'm trying to write a Bash script that will overwrite an existing directory.我正在尝试编写一个 Bash 脚本来覆盖现有目录。 I have a directory foo/ and I am trying to overwrite bar/ with it.我有一个目录foo/ ,我试图用它覆盖bar/ But when I do this:但是当我这样做时:

cp -Rf foo/ bar/

a new bar/foo/ directory is created.创建一个新的bar/foo/目录。 I don't want that.我不想要那个。 There are two files in foo/ ; foo/中有两个文件; a and b . ab There are files with same names in bar/ as well. bar/中也有同名文件。 I want the foo/a and foo/b to replace bar/a and bar/b .我希望foo/afoo/b替换bar/abar/b

You can do this using -T option in cp .您可以使用cp -T选项执行此操作。
See Man page for cp .请参阅cp页。

-T, --no-target-directory
    treat DEST as a normal file

So as per your example, following is the file structure.因此,根据您的示例,以下是文件结构。

$ tree test
test
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

You can see the clear difference when you use -v for Verbose.当您将-v用于 Verbose 时,您可以看到明显的区别。
When you use just -R option.当您仅使用-R选项时。

$ cp -Rv foo/ bar/
`foo/' -> `bar/foo'
`foo/b' -> `bar/foo/b'
`foo/a' -> `bar/foo/a'
 $ tree
 |-- bar
 |   |-- a
 |   |-- b
 |   `-- foo
 |       |-- a
 |       `-- b
 `-- foo
     |-- a
     `-- b
3 directories, 6 files

When you use the option -T it overwrites the contents, treating the destination like a normal file and not directory .当您使用选项-T它会覆盖内容,将目标视为普通文件而不是 directory

$ cp -TRv foo/ bar/
`foo/b' -> `bar/b'
`foo/a' -> `bar/a'

$ tree
|-- bar
|   |-- a
|   `-- b
`-- foo
    |-- a
    `-- b
2 directories, 4 files

This should solve your problem.这应该可以解决您的问题。

If you want to ensure bar/ ends up identical to foo/ , use rsync instead:如果要确保bar/最终与foo/相同,请改用rsync

rsync -a --delete foo/ bar/

If just a few things have changed, this will execute much faster than removing and re-copying the whole directory.如果只是一些事情发生了变化,这将比删除和重新复制整个目录的执行速度快得多。

  • -a is 'archive mode', which copies faithfully files in foo/ to bar/ -a是“归档模式”,将foo/文件忠实地复制到bar/
  • --delete removes extra files not in foo/ from bar/ as well, ensuring bar/ ends up identical --deletebar/删除不在foo/中的额外文件,确保bar/最终相同
  • If you want to see what it's doing, add -vh for verbose and human-readable如果您想查看它在做什么,请添加-vh以获取详细且易于阅读的内容
  • Note: the slash after foo is required, otherwise rsync will copy foo/ to bar/foo/ rather than overwriting bar/ itself.注意: foo后面的斜杠是必需的,否则rsync会将foo/复制到bar/foo/而不是覆盖bar/本身。
    • (Slashes after directories in rsync are confusing; if you're interested, here's the scoop. They tell rsync to refer to the contents of the directory, rather than the directory itself . So to overwrite from the contents of foo/ onto the contents of bar/ , we use a slash on both. It's confusing because it won't work as expected with a slash on neither , though; rsync sneakily always interprets the destination path as though it has a slash, even though it honors an absence of a slash on the source path. So we need a slash on the source path to make it match the auto-added slash on the destination path, if we want to copy the contents of foo/ into bar/ , rather than the directory foo/ itself landing into bar/ as bar/foo .) (在rsync的目录后斜杠混乱;如果你有兴趣,这里的勺子他们告诉rsync将参照目录的内容,而不是目录本身于是从内容覆盖。 foo/到的内容bar/ ,我们在两者上都使用斜杠。这很令人困惑,因为它不会按预期工作,但在两者都没有斜杠;rsync 偷偷摸摸地总是将目标路径解释为好像有斜杠,即使它尊重没有源路径上的斜杠。因此,如果我们要将foo/内容复制到bar/而不是目录foo/本身,则需要在源路径上添加斜杠以使其与目标路径上自动添加的斜杠匹配登陆bar/作为bar/foo 。)

rsync is very powerful and useful, if you're curious look around for what else it can do (such as copying over ssh). rsync非常强大且有用,如果您好奇,可以四处看看它还能做什么(例如通过 ssh 复制)。

Do it in two steps.分两步做。

rm -r bar/
cp -r foo/ bar/

使用这个cp命令:

cp -Rf foo/* bar/

以下命令可确保副本中包含点文件(隐藏文件):

$ cp -Rf foo/. bar

Very similar to @Jonathan Wheeler:与@Jonathan Wheeler 非常相似:

If you do not want to remember, but not rewrite bar :如果你不想记住,但不要重写bar

rm -r bar/
cp -r foo/ !$

!$ displays the last argument of your previous command. !$显示上一个命令的最后一个参数。

这应该可以解决您的问题。

\cp -rf foo/* bar/

In case you're in Git Bash for Windows :如果你在Git Bash 为 Windows

robocopy path/to/source path/to/target -MIR

-MIR means mirror, it'll result in two identical folders. -MIR表示镜像,它会产生两个相同的文件夹。 Existing files will be skipped, extra files will be deleted.现有文件将被跳过,多余的文件将被删除。

The operation you defined is a "merge" and you cannot do that with cp .您定义的操作是“合并”,您不能使用cp执行此操作。 However, if you are not looking for merging and ok to lose the folder bar then you can simply rm -rf bar to delete the folder and then mv foo bar to rename it.但是,如果您不是在寻找合并并且可以丢失文件夹bar那么您可以简单地rm -rf bar删除文件夹,然后mv foo bar重命名它。 This will not take any time as both operations are done by file pointers, not file contents.这不会花费任何时间,因为这两个操作都是由文件指针完成的,而不是文件内容。

尝试使用这个由两步组成的命令:

rm -rf bar && cp -r foo bar

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在不确认的情况下强制 cp 覆盖 - How to force cp to overwrite without confirmation 如何将所有文件从一个目录移动(并覆盖)到另一个目录? - How to move (and overwrite) all files from one directory to another? 使用cp命令将一组文件复制到另一组(具有相同的名称),而不进行覆盖和重命名 - using cp command to copy one set of files to another set (with same names) without overwrite and with renaming 如何使用cp将文件复制到与目录中一个目录名称相同的文件? - how to use cp to copy a file to to a file named the same as one directory name in a directory? LINUX CP:我需要将所有文件从一个目录复制到另一个目录而不复制任何子目录 - LINUX CP: I need to copy all files from one directory to another without copying any sub-directories 如何强制一个线程在另一个线程之前启动? - How to force a thread to start before another one? 如何使用“cp”命令排除特定目录? - How to use 'cp' command to exclude a specific directory? 如何强制Icecast在YP目录中列出一个安装文件? - How to force Icecast to list one mount on YP Directory? 删除目录中的文件,而不是整个目录 - Remove files inside directory instead of the whole directory 如何使用cp从不同的目录复制多个文件? - How to copy multiple files from a different directory using cp?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM