How to force 'cp' to overwrite directory instead of creating another one inside? How to force 'cp' to overwrite directory instead of creating another one inside? linux linux

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


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 testtest|-- bar|   |-- a|   `-- b`-- foo    |-- a    `-- b2 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     `-- b3 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    `-- b2 directories, 4 files

This should solve your problem.


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.
    • (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 is very powerful and useful, if you're curious look around for what else it can do (such as copying over ssh).


Do it in two steps.

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