How to force 'cp' to overwrite directory i

2019-01-30 13:21发布

I'm trying to write a Bash script that will overwrite an existing directory. So, I have a directory foo/ and I am trying to overwrite bar/ with it. But when I do,

cp -Rf foo/ bar/

what happens is that a new bar/foo/ directory is created. I don't want that. There are two files in foo/ a and b. There are files with same names in bar/ as well. I want the foo/a and foo/b to replace bar/a and bar/b.

6条回答
姐就是有狂的资本
2楼-- · 2019-01-30 13:37

The following command ensures dotfiles (hidden files) are included in the copy:

$ cp -Rf foo/. bar
查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-01-30 13:38

If you want to ensure bar/ ends up identical to foo/, use rsync instead:

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/
  • --delete removes extra files not in foo/ from bar/ as well, ensuring bar/ ends up identical
  • If you want to see what it's doing, add -vh for verbose and human-readable
  • Note: the slash after foo is required, otherwise rsync will copy foo/ to bar/foo/ rather than overwriting bar/ itself

rsync is very powerful and useful, if you're curious look around for what else it can do (such as copying over ssh).

查看更多
ゆ 、 Hurt°
4楼-- · 2019-01-30 13:46

You can do this using -T option in cp.
See Man page for 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.
When you use just -R option.

$ 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.

$ 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.

查看更多
狗以群分
5楼-- · 2019-01-30 14:00

Very similar to @Jonathan Wheeler:

If you do not want to remember, but not rewrite bar:

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

!$ displays the last argument of your previous command.

查看更多
萌系小妹纸
6楼-- · 2019-01-30 14:01

Do it in two steps.

rm -r bar/
cp -r foo/ bar/
查看更多
来,给爷笑一个
7楼-- · 2019-01-30 14:01

Use this cp command:

cp -Rf foo/* bar/
查看更多
登录 后发表回答