[英]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
. a
和b
。 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/a
和foo/b
替换bar/a
和bar/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 --delete
从bar/
删除不在foo/
中的额外文件,确保bar/
最终相同-vh
for verbose and human-readable如果您想查看它在做什么,请添加-vh
以获取详细且易于阅读的内容foo
is required, otherwise rsync
will copy foo/
to bar/foo/
rather than overwriting bar/
itself.注意: foo
后面的斜杠是必需的,否则rsync
会将foo/
复制到bar/foo/
而不是覆盖bar/
本身。
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.