Linux

rsync - 在排除指令中使用 * 和 ** 有什麼區別?

  • January 10, 2021

繼我關於 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

上面的命令通過源目錄的每個子目錄遞歸併在每個文件上應用包含和排除模式……那麼它如何“看到”目錄分隔符?

有人可以給出一個場景,可能像上面那樣,展示匹配目錄分隔符的*失敗和成功嗎?**

乾杯。

讓我們添加一些目錄和文件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.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文件。**類似於,*但也匹配目錄分隔符/(ofsub1/sub1/sub2/)。

將 a 顯示**為排除(如問題的標題)有點困難,因為--exclude='*'排除了下面的第一級,"$openWrtPath"這也意味著已經排除了任何子目錄和文件(因為排除了級別 1 的父目錄)。使用**不會有什麼不同。


要包含目錄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.
[...]

引用自:https://unix.stackexchange.com/questions/628355