问题
I'm trying to write a Bash script that will overwrite an existing directory. I have a directory foo/
and I am trying to overwrite bar/
with it. But when I do this:
cp -Rf foo/ bar/
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
.
回答1:
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.
回答2:
Do it in two steps.
rm -r bar/
cp -r foo/ bar/
回答3:
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 infoo/
tobar/
--delete
removes extra files not infoo/
frombar/
as well, ensuringbar/
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, otherwisersync
will copyfoo/
tobar/foo/
rather than overwritingbar/
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 ofbar/
, 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 offoo/
intobar/
, rather than the directoryfoo/
itself landing intobar/
asbar/foo
.)
- (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
rsync
is very powerful and useful, if you're curious look around for what else it can do (such as copying over ssh).
回答4:
Use this cp
command:
cp -Rf foo/* bar/
回答5:
The following command ensures dotfiles (hidden files) are included in the copy:
$ cp -Rf foo/. bar
回答6:
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.
回答7:
The operation you defined is a "merge" and you cannot do that with 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. This will not take any time as both operations are done by file pointers, not file contents.
回答8:
Try to use this composed of two steps command:
rm -rf bar && cp -r foo bar
来源:https://stackoverflow.com/questions/23698183/how-to-force-cp-to-overwrite-directory-instead-of-creating-another-one-inside