Linux 如何强制';cp';要覆盖目录而不是在其中创建另一个目录?

Linux 如何强制';cp';要覆盖目录而不是在其中创建另一个目录?,linux,bash,shell,command-line,cp,Linux,Bash,Shell,Command Line,Cp,我正在尝试编写一个Bash脚本,该脚本将覆盖现有目录。我有一个目录foo/,我正试图用它覆盖bar/。但当我这么做的时候: cp -Rf foo/ bar/ 将创建一个新的bar/foo/目录。我不想那样。foo/中有两个文件a和b。bar/中也有同名文件。我希望foo/a和foo/b替换bar/a和bar/b使用此cp命令: cp -Rf foo/* bar/ 分两步做 rm -r bar/ cp -r foo/ bar/ 您可以使用cp中的-T选项执行此操作 参见手册页了解cp -T,

我正在尝试编写一个Bash脚本,该脚本将覆盖现有目录。我有一个目录
foo/
,我正试图用它覆盖
bar/
。但当我这么做的时候:

cp -Rf foo/ bar/

将创建一个新的
bar/foo/
目录。我不想那样。
foo/
中有两个文件<代码>a和
b
bar/
中也有同名文件。我希望
foo/a
foo/b
替换
bar/a
bar/b
使用此
cp
命令:

cp -Rf foo/* bar/
分两步做

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

您可以使用
cp
中的
-T
选项执行此操作
参见手册页了解
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
进行详细描述时,您可以看到明显的区别。
当您仅使用
-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

这将解决您的问题。

以下命令可确保副本中包含点文件(隐藏文件):

$ cp -Rf foo/. bar

与@Jonathan Wheeler非常相似:

如果您不想记住,但不想重写
bar

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

$
显示上一个命令的最后一个参数。

如果要确保
bar/
最终与
foo/
相同,请使用
rsync

rsync -a --delete foo/ bar/
如果只是一些事情发生了变化,那么这将比删除和重新复制整个目录快得多

  • -a
    是“归档模式”,它将
    foo/
    中的文件忠实地复制到
    bar/
  • --delete
    也从
    bar/
    中删除不在
    foo/
    中的额外文件,确保
    bar/
    结果相同
  • 如果您想查看它在做什么,请添加
    -vh
    ,以获得详细和可读性
  • 注意:
    foo
    后的斜杠是必需的,否则
    rsync
    foo/
    复制到
    bar/foo/
    而不是覆盖
    bar/
    本身。
    • (rsync中目录后的斜杠令人困惑;如果您感兴趣,这里是独家新闻。它们告诉rsync引用目录的内容,而不是目录本身。因此,要将
      foo/
      的内容覆盖到
      bar/
      的内容,我们在两者上都使用斜杠。这会让人困惑,因为它不会像预期的那样工作但是,这两条路径上都没有斜杠。rsync总是偷偷地将目标路径解释为有斜杠,即使它承认源路径上没有斜杠。因此,如果我们想将
      foo/
      的内容复制到
      栏中,我们需要在源路径上有斜杠,使其与目标路径上自动添加的斜杠匹配/
      ,而不是目录
      foo/
      本身作为
      bar/foo
      登录到
      bar/

rsync
非常强大和有用,如果您想知道它还能做什么(例如通过ssh复制)。

您定义的操作是“合并”使用
cp
无法实现这一点。但是,如果您不希望合并并确定丢失文件夹
bar
,那么您只需
rm-rf bar
删除文件夹,然后
mv foo bar
对其进行重命名。这不会花费任何时间,因为这两个操作都是通过文件指针完成的,而不是文件内容。

尝试to使用由两个步骤组成的命令:

rm -rf bar && cp -r foo bar

这应该能解决你的问题

\cp -rf foo/* bar/

这不会删除存在于bar中但不在foo中的文件。我不知道这是什么意思。为什么
cp
命令要从源代码中删除文件?我的理解是,当您用另一个目录“覆盖现有目录”时,被覆盖的目录最后应该是另一个目录的副本。也就是说,在bar的末尾应该是复制foo,就像@jonathan wheeler answer一样,但是如果你有一个文件bar/c而没有foo/c,那么bar/c就不会被删除。另一方面,我注意到Saurabh Meshram的答案也不是这样。也许我们不同意覆盖的意思,对我来说它基本上是替换,而你可能是指megre?这很难为了准确地告诉OP想要什么,因为她只提到了两个文件,它们都在foo和bar中。这种语法也忽略了隐藏的点文件。大量的点文件也可能会炸毁全局。万一有人被它绊倒,它将无法与OSX cp一起工作。虽然上面给出的示例不清楚这个答案是否是OP想要的问题…使用-T选项时,文件位于现有目标(
bar/
)中,但不在源(
foo/
)中将被放置在适当的位置,所以这不是大多数人会考虑的完全覆盖目录。例如,如果<代码> BA/BZ已经存在,它随后仍然存在……这个答案确实回答了OP问题,但是没有解决如果目的地已经存在并且要删除它所包含的内容的情况。源目录没有。这不是将文件从一个位置复制到另一个位置的预期行为。它只会覆盖目标中也在源中的内容,不会触及目标中不在源中的任何内容。您可以通过预先输入命令来清理目标文件夹:
rm-rf bar/*&&cp-TRv foo/bar/
我不是一个读心术的人……我看不出OP想要的是什么,但这肯定是我(MEEEE)想要的答案我正在寻找,以防有人被投票最多的评论中的链接不起作用的原因绊倒,这里是:这是真的吗?看起来很不寻常。@Mateng我刚刚测试了它-是的,它是真的。
表示目录中的所有文件。因此,隐藏的