Как заставить "cp" перезаписать каталог вместо создания другого внутри?

Я пытаюсь написать Bash script, который перезапишет существующий каталог. Итак, у меня есть каталог foo/, и я пытаюсь перезаписать его с помощью bar/. Но когда я это делаю,

cp -Rf foo/ bar/

происходит то, что создается новый каталог bar/foo/. Я не хочу этого. В файлах foo/a и b есть два файла. В барах также есть файлы с одинаковыми именами. Я хочу, чтобы foo/a и foo/b заменили bar/a и bar/b.

Ответ 1

Вы можете сделать это, используя опцию -T в cp.
См. Страницу "Человек" для cp.

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

В соответствии с вашим примером следующая структура файла.

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

Вы можете видеть явное различие при использовании -v для Verbose.
Когда вы используете только параметр -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

Когда вы используете опцию -T, она перезаписывает содержимое, обрабатывает назначение как обычный файл, а не каталог.

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

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

Это должно решить вашу проблему.

Ответ 2

Сделайте это в два этапа.

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

Ответ 3

Используйте эту команду cp:

cp -Rf foo/* bar/

Ответ 4

Следующая команда обеспечивает, чтобы в копии были включены dotfiles (скрытые файлы):

$ cp -Rf foo/. bar

Ответ 5

Если вы хотите, чтобы bar/ заканчивался идентичным foo/, вместо этого используйте rsync:

rsync -a --delete foo/ bar/

Если только несколько вещей изменились, это будет выполняться намного быстрее, чем удаление и повторное копирование всего каталога.

  • -a - это "режим архива", который точно копирует файлы в foo/ to bar/
  • --delete удаляет файлы не в foo/ from bar/
  • Если вы хотите посмотреть, что он делает, добавьте -vh для подробного и -vh для человека
  • Примечание: требуется косая черта после foo, иначе rsync скопирует foo/ в bar/foo/ вместо того, чтобы переписать bar/ self

rsync очень мощный и полезный, если вам любопытно посмотреть, что еще он может сделать (например, копирование через ssh).

Ответ 6

Очень похоже на @Jonathan Wheeler:

Если вы не хотите помнить, но не переписываете bar:

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

!$ отображает последний аргумент предыдущей команды.