如何在 Linux 中将目录复制到现有目录?

linuxopen sourceoperating system更新于 2026/1/27 16:37:17

概述

复制文件是使用 Linux Shell 执行的最常见操作之一。我们通常使用 cp(复制)命令来实现此目的。

我们将讨论如何递归地将文件夹移动到另一个位置(包括覆盖或不覆盖)。

问题介绍

首先,我们需要了解"将文件夹复制到另一个位置"在本题中的含义。

一个好的例子可以帮助您更好地理解。

$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└──  target
     └── originalTarget.file

3 个目录,4 个文件

如上图所示,src 文件夹下有两个目录。其中包含一些源代码文件和一个子文件夹。此外,还有一个隐藏文件。

现在我们需要将源文件夹复制到目标文件夹。

我们希望目标文件夹与源文件夹完全相同。

├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└──  target
     ├── .hidden.file
     ├── srcFile.txt
     └── subSrc
         └── subSrcFile.txt

但是,如果我们只是将源文件夹的内容复制到目标文件夹,我们希望 src 下的所有内容都递归移动到目标文件夹。我们还希望目标文件夹下的原始文件保持不变。

├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── .hidden.file
    ├── originalTarget.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

由于目标目录已经存在,我们不能直接使用 cp -r src target 方法来执行此任务。相反,我们需要先在目标目录中创建一个名为 src 的新目录。然后,我们可以将文件从 src 移动到新创建的 src 目录中。

之后,我们将讨论如何通过两种不同的方法实现我们的目标 -

  • 使用 cp 命令

  • 使用 rsync 命令

使用 cp  命令

我们首先来看看如何使用 cp 命令来解决这个问题,因为这很常见。

cp 命令不覆盖目标目录

如果源文件夹不为空,我们不能简单地使用 cp 命令将源文件夹的内容复制到目标文件夹。

但是,cp 命令有一个 -i 选项,它会将源文件视为常规文件,而不是文件夹。

如果我们使用 −rT 选项,那么 cp 命令将递归遍历源文件夹的内容,并在目标文件夹中创建它们的副本。

$ cp -rT src target
$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── .hidden.file
    ├── originalTarget.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

4 个目录,7 个文件

tree 的 -a 选项告诉我们,我们将源目录中的所有内容复制到目标目录中。但是,复制操作并不包含源目录。所以,我们完成了!

Bash 通配符技巧

我们已经通过使用带有 -rT 选项的 cp 命令解决了这个问题。

我们可以通过将 src 中的所有内容复制到 target 来解决这个问题。因此,我们可以这样写:cp -r src/* target。

我们可以通过将 src 中的所有内容复制到 target 来解决这个问题。因此,我们可以这样写:cp -r src/* target。

$ cp -r src/* target
$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── originalTarget.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

4 个目录,6 个文件

如树状图所示,src 下的大多数文件都已成功传输到目标文件夹,.dot 文件除外。这是因为使用"globstar"选项后,shell 会忽略任何以句点(".")开头的文件名。

有两种方法可以解决这个问题。一种方法是修改全局设置,使通配符包含 .dot 文件。您可以使用 shopt -s dotglob 命令来实现。

$ ( shopt -s dotglob; cp -r src/* target )
$ tree -a target
target
├──  .hidden.file
├──  originalTarget.file
├──  srcFile.txt
└──  subSrc
     └── subSrcFile.txt

1 directory, 4 files

$ shopt dotglob
dotglob off

从上面的输出中我们可以看到,点文件也已成功创建。此外,我们将 shoptcp 命令与 cp 命令一起用括号 (…) 括起来,这样它们就可以在子 shell 中运行,因为我们希望 shoptcp 命令只影响单个 cp 命令。

命令执行后,当我们检查通配符选项时,它们仍然处于禁用状态。

更改 bash 的默认行为很容易。但是,如果您自己编写脚本,这可能会带来不便。尤其是在您想避免意外后果的情况下。

您还可以使用"src/."而不是"src/*"将 .dotfiles 添加到源代码控制系统中。

让我们看看它是否按预期工作。

$ cp -r src/. target
$ tree -a target
target
├──  .hidden.file
├──  originalTarget.file
├──  srcFile.txt
└──  subSrc
     └── subSrcFile.txt

1 directory, 4 files

cp 并覆盖目标目录

如果我们想用目标文件夹的内容替换源文件夹的内容,那么使用 -R 选项比 -O 选项更简单。因此,我们先删除目标文件夹,然后运行 ​​cp -r 命令。

$ rm -r target && cp -r src target
$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── .hidden.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

4 个目录,6 个文件

使用 rsync 命令

rsync 是解决此问题的实用工具。

不覆盖目标目录的 rsync

我们可以使用两个 rsync 命令行来递归复制目录 -

rsync -a source target:将源目录的内容复制到目标目录

rsync -a src/ target-将 src 目录的内容复制到目标目录

上面两个命令几乎完全相同。以斜杠开头的那个正是我们要找的。

让我们在我们的示例中测试一下 -

$ rsync -a src/ target
$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── .hidden.file
    ├── originalTarget.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

4 个目录,7 个文件

树的结果表明该命令解决了我们的问题。

rysnc 并覆盖目标目录

我们已经了解到,可以结合使用两个命令行"sudo rmdir /path/to/folder && sudo cp -r /source/folder /path/to/destination"来解决问题。

使用 rsync,我们可以一次性完成所有操作 -

$ rsync -a --delete src/ target
$ tree -a
.
├──  src
│    ├── .hidden.file
│    ├── srcFile.txt
│    └── subSrc
│        └── subSrcFile.txt
└── target
    ├── .hidden.file
    ├── srcFile.txt
    └── subSrc
        └── subSrcFile.txt

4 个目录,6 个文件

执行 rsync 命令后,目标和源都包含相同的内容。因此,我们找到了原始问题的替代解决方案。

此解决方案的秘诀在于 -delete 开关。

-delete 选项指示 rsync 从 target/ 中删除任何在 source/ 中不存在的文件,以确保传输结束时源和目标文件完全相同。

结论

我们讨论了如何递归地将一个文件夹移动到另一个文件夹中(包括覆盖和不覆盖)。

我们学习了两种解决问题的方法:使用常见的 cp(复制)和 rsync 命令。

我们讨论了 bash 的 dotglob 设置及其如何影响通配符行为。


相关文章


有用资源