我正在尝试编写一个 Bash 脚本,它将覆盖现有的目录。我有一个目录 foo/,我试图用它覆盖 bar/。但是当我这么做的时候:
foo/
bar/
cp -Rf foo/ bar/
创建一个新的 bar/foo/目录。我不想那样。在 foo/中有两个文件: a和 b。在 bar/中也有同名的文件。我想用 foo/a和 foo/b代替 bar/a和 bar/b。
bar/foo/
a
b
foo/a
foo/b
bar/a
bar/b
使用这个 cp命令:
cp
cp -Rf foo/* bar/
分两步做。
rm -r bar/ cp -r foo/ bar/
您可以在 cp中使用 -T选项来完成此操作。 参见 cp的手册页。
-T
-T, --no-target-directory treat DEST as a normal file
因此,根据您的示例,下面是文件结构。
$ tree test test |-- bar | |-- a | `-- b `-- foo |-- a `-- b 2 directories, 4 files
在对详细信息使用 -v时,您可以看到明显的区别。 当您只使用 -R选项时。
-v
-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
这应该能解决你的问题。
下面的命令确保 dotfiles (隐藏文件)包含在副本中:
$ cp -Rf foo/. bar
与@Jonathan Wheeler 非常相似:
如果你不想记住,但不重写 bar:
bar
rm -r bar/ cp -r foo/ !$
!$显示上一个命令的最后一个参数。
!$
如果您想确保 bar/最终与 foo/完全相同,请使用 rsync:
rsync
rsync -a --delete foo/ bar/
如果只有少数内容发生了更改,执行速度将远远快于删除和重新复制整个目录。
-a
--delete
-vh
foo
bar/foo
rsync非常强大和有用,如果您对它的其他功能感到好奇,可以查看它的其他功能(比如通过 ssh 进行复制)。
您定义的操作是一个“ merge”,您不能对 cp执行该操作。但是,如果你不寻找合并和确定丢失的文件夹 bar,那么你可以简单地 rm -rf bar删除文件夹,然后 mv foo bar重命名它。这不会花费任何时间,因为这两个操作都是由文件指针完成的,而不是文件内容。
rm -rf bar
mv foo bar
尝试使用这个由两个步骤组成的命令:
\cp -rf foo/* bar/
如果你在 用于 Windows 的 Git Bash:
robocopy path/to/source path/to/target -MIR
-MIR意味着镜像,它将导致两个相同的文件夹。现有的文件将被跳过,额外的文件将被删除。
-MIR