继我的关于rsync的其他问题。
我试图了解包含/排除指令如何使用模式来匹配源目录中的文件名称,以决定将哪些文件同步到目标目录。
显然*
不匹配目录分隔符,但**
可以匹配一个(准确地说是零个或多个)。有人可以用一些 rsync 命令非常清楚地解释这意味着什么吗?
例如:
这是我的源目录结构:
../openwrt
../openwrt/afile.txt
../openwrt/BackupOfSettings
../openwrt/BackupOfSettings/file1.txt
../openwrt/BackupOfSettings/file2.txt
../openwrt/BackupOfSettings/file3.tar.gz
../openwrt/BackupOfPackages
../openwrt/BackupOfImages
../openwrt/BackupOfImages/anotherfile.txt
../openwrt/BackupOfImages/yetanotherfile.jpg
我的源目录和目标目录:
openWrtPath="/mnt/usb/openwrt/"
ncpPath="/media/myCloudDrive/openwrt"
命令示例:
此命令将仅同步“BackupOfSettings”文件夹中扩展名为 tar.gz 的文件。
rsync -vvritn --include='BackupOfSettings/' --include='BackupOfSettings/*.tar.gz' --exclude='*' $openWrtPath $ncpPath
上面的命令递归遍历源目录的每个子目录,并对每个文件应用包含和排除模式......那么它如何“看到”目录分隔符呢?
有人可以给出一个场景,也许像上面那样,演示匹配目录分隔符的*
失败和成功吗?**
干杯。
答案1
让我们添加一些目录和文件来BackupOfSettings
测试设置:
mkdir -p "$openWrtPath"/BackupOfSettings/sub1/sub2
touch "$openWrtPath"/BackupOfSettings/file1.tar.gz
touch "$openWrtPath"/BackupOfSettings/sub1/file2.tar.gz
touch "$openWrtPath"/BackupOfSettings/sub1/sub2/file3.tar.gz
我们还将子目录添加sub1
到sub1/sub2
命令中:
rsync -vvritn \
--include='BackupOfSettings/' \
--include='BackupOfSettings/sub1/' \
--include='BackupOfSettings/sub1/sub2/' \
--include='BackupOfSettings/*.tar.gz' \
--exclude='*' "$openWrtPath" "$ncpPath"
这会同步BackupOfSettings/file1.tar.gz
、BackupOfSettings/sub1/
和BackupOfSettings/sub1/sub2/
,但不会同步子目录内的任何文件,因为*
与/
.
现在让我们尝试BackupOfSettings/**.tar.gz
包含:
rsync -vvritn \
--include='BackupOfSettings/' \
--include='BackupOfSettings/sub1/' \
--include='BackupOfSettings/sub1/sub2/' \
--include='BackupOfSettings/**.tar.gz' \
--exclude='*' "$openWrtPath" "$ncpPath"
这包括所有三个*.tar.gz
文件。类似于,但也**
匹配*
目录分隔符/
(sub1/
和sub1/sub2/
)。
将 a 显示**
为排除(如问题标题中所示)有点困难,因为--exclude='*'
排除下面的第一级"$openWrtPath"
也意味着所有子目录和文件都已被排除(因为第一级的父目录被排除)。使用**
不会有什么区别。
要包含目录BackupOfSettings
以及该目录下的任何子目录,您可以将上述三个目录包含替换为
--include='BackupOfSettings/' \
--include='BackupOfSettings/**/' \
或者
--include='BackupOfSettings/***/' \
从man rsync
:
[...]
o a ’*’ matches any path component, but it stops at slashes.
o use ’**’ to match anything, including slashes.
[...]
o if the pattern contains a / (not counting a trailing /) or a "**", then it
is matched against the full pathname, including any leading directories.
If the pattern doesn’t contain a / or a "**", then it is matched only
against the final component of the filename. (Remember that the algorithm
is applied recursively so "full filename" can actually be any portion of a
path from the starting directory on down.)
o a trailing "dir_name/***" will match both the directory (as if "dir_name/"
had been specified) and everything in the directory (as if "dir_name/**"
had been specified). This behavior was added in version 2.6.7.
[...]
答案2
shell 可以将双星号解释为特殊的通配符。也可以看看man bash
:
globstar
If set, the pattern ** used in a pathname expansion context will match
all files and zero or more directories and subdirectories.
If the pattern is followed by a /, only directories and subdirectories match.