rsync - 在排除指令中使用 * 和 ** 有什么区别?

rsync - 在排除指令中使用 * 和 ** 有什么区别?

继我的关于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

我们还将子目录添加sub1sub1/sub2命令中:

rsync -vvritn \
  --include='BackupOfSettings/' \
  --include='BackupOfSettings/sub1/' \
  --include='BackupOfSettings/sub1/sub2/' \
  --include='BackupOfSettings/*.tar.gz' \
  --exclude='*' "$openWrtPath" "$ncpPath"

这会同步BackupOfSettings/file1.tar.gzBackupOfSettings/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.

相关内容