在递归地复制目录时跳过隐藏的文件和目录
1. 概述
当我们想在 Linux 命令行中递归地复制目录时,cp -r可能是第一个出现的命令。
我们知道点文件在 Linux 中被视为隐藏文件。有时,当我们递归复制目录时,我们希望排除目录下的隐藏文件和目录。
在本快速教程中,我们将学习如何实现这一目标。
2. 问题介绍
首先,让我们建立一个目录树作为例子:
$ tree -a parentDir
parentDir
├── file1
├── file2
├── .hidden_dir
│ ├── .hidden_sub2
│ ├── sub2_file1
│ └── sub2_file2
├── .hidden_parent
└── sub1
├── .hidden_sub1
├── sub1_file1
└── sub1_file2
2 directories, 9 files
我们使用了方便的tree 命令来呈现 parentDir目录下的内容。
由于目录及其子目录包含隐藏文件和目录,我们将*-a*选项传递给 tree命令以显示隐藏对象。
现在,让我们 使用cp -r命令递归地将parentDir复制到一个新目录,比如parentDir2:
$ cp -r parentDir parentDir2
$ tree -a parentDir2
parentDir2
├── file1
├── file2
├── .hidden_parent
├── sub1
│ ├── .hidden_sub1
│ ├── sub1_file1
│ └── sub1_file2
└── .hidden_dir
├── .hidden_sub2
├── sub2_file1
└── sub2_file2
2 directories, 9 files
如上面的输出所示,目录已成功复制。但是,我们也将这些隐藏文件复制到了新目录中。
我们的目标是递归地复制目录,不包括隐藏的目录和文件。
接下来,让我们看看如何解决这个问题。
3. 复制所有内容然后删除隐藏文件
一个想法可能会解决这个问题:首先递归地复制所有内容,然后从目标目录中删除隐藏对象。
现在,让我们将这个想法转化为命令并试一试:
$ cp -r parentDir parentDir2 && find parentDir2 -name '.*' | xargs rm -rf
$ tree -a parentDir2
parentDir2
├── file1
├── file2
└── sub1
├── sub1_file1
└── sub1_file2
1 directory, 4 files
我们将cp -r命令和“ find and delete ”命令与“ && ”结合起来,这样find命令只有在cp -r*命令成功运行*时才会启动。
正如我们在 tree输出中看到的,所有隐藏对象都不在 parentDir2目录中。因此该命令适用于该示例。
这种方法很简单,适用于大多数情况。但是,它可能存在一些问题。那么接下来,让我们仔细看看它们。
首先,隐藏的文件或目录可能很大。如果是这种情况,这种方法将不必要地复制大对象然后删除它们。也就是说,它可能会导致性能问题。
在更坏的情况下,如果隐藏的对象足够大,目标设备可能没有足够的空间来存储它们。因此,该命令可能会失败。
其次,有时隐藏文件或目录包含敏感数据。这就是我们要在复制过程中排除它们的原因之一。
如果我们将所有内容复制到目标,敏感数据将自动传输到目标设备。我们可能认为这没问题,因为我们在cp命令完成后立即删除它们。
一旦复制命令失败或需要很长时间,敏感数据可能会在不安全的设备上保留很长时间。此外,如果目标设备是远程文件系统,我们不知道文件同步服务是否正在运行。
因此,如果隐藏对象包含敏感数据,这种方法可能会产生安全漏洞。
4. 使用rsync命令
rsync是一个功能强大且方便的文件复制实用程序。它接受两个有价值的选项,允许我们在复制期间包含或排除文件: –include=PATTERN 和*–exclude=PATTERN*。
要跳过隐藏文件和目录,我们可以将“.*”模式传递给*–exclude*选项。我们应该注意,这里的“.*”模式不是正则表达式。相反,它表示任何以点开头的文件名或目录名。
现在,让我们试一试:
$ rsync -av --exclude=".*" parentDir/* parentDir3
sending incremental file list
created directory parentDir3
file1
file2
sub1/
sub1/sub1_file1
sub1/sub1_file2
sent 315 bytes received 137 bytes 904.00 bytes/sec
total size is 0 speedup is 0.00
$ tree -a parentDir3
parentDir3
├── file1
├── file2
└── sub1
├── sub1_file1
└── sub1_file2
1 directory, 4 files
如上面的输出所示,所有隐藏对象都不会复制到 parentDir3目录。因此,该命令完成了这项工作。
rsync命令支持过滤器选项*-f *以使包含/排除定义更容易。
例如,我们可以将命令写成更短的形式:
rsync -av -f "- .*" parentDir/* parentDir3
在上面的命令中,-f 选项定义了一个 过滤器,并且遵循一个规则。当rsync工作时,它将对需要复制的文件应用过滤器。
**加号“+”表示“包含”,而减号“-”表示“排除”。**因此,在我们的命令中,我们通过“-.*”排除所有隐藏文件和目录。