Bash

rsync:如何排除多種文件類型?

  • May 26, 2021

這是在執行 Catalina 的 Mac 上使用 bash:

這有效:

rsync -Pa --rsh="ssh -p 19991" --exclude '*.jpg' --exclude '*.mp4' pi@localhost:/home/pi/webcam /Volumes/Media/Webcam\ Backups/raspcondo/webcam/

這些不會:

rsync -Pa --rsh="ssh -p 19991" --exclude={'*.jpg', '*.mp4'} pi@localhost:/home/pi/webcam /Volumes/Media/Webcam\ Backups/raspcondo/webcam/

rsync -Pa --rsh="ssh -p 19991" --exclude {'*.jpg', '*.mp4'} pi@localhost:/home/pi/webcam /Volumes/Media/Webcam\ Backups/raspcondo/webcam/

這是輸出:

building file list ...
rsync: link_stat "/Users/mnewman/*.mp4}" failed: No such file or directory (2)
rsync: link_stat "/Users/mnewman/pi@localhost:/home/pi/webcam" failed: No such file or directory (2)
0 files to consider
sent 29 bytes  received 20 bytes  98.00 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files could not be transferred (code 23) at /AppleInternal/BuildRoot/Library/Caches/com.apple.xbs/Sources/rsync/rsync-54.120.1/rsync/main.c(996) [sender=2.6.9]

我對要排除的文件類型列表做錯了什麼?

首先,您的第一個範例有效-使用它有什麼問題?

如果您真的不想這樣做,請嘗試--exclude=*.{jpg,mp4},它將(在某些 shell 中)擴展為--exclude=*.jpg --exclude=*.mp4,但請注意:

  1. 這是一個稱為Brace Expansion的shell 功能。它不是rsync 或 rsync 過濾規則的功能。

如果您錯誤地認為 rsync 將使用大括號本身(它不會,也不能,甚至永遠不會看到大括號),這很容易導致混亂和“令人驚訝”的行為。 2. 擴展是rsync 執行之前完成的。rsync 只能看到,例如, --exclude=*.mp4 因為在目前目錄中沒有與該模式匹配的文件名。 3. 萬一有任何文件名匹配--exclude=*.mp4--exclude=*.jpg,大括號擴展將擴展為那些確切的文件名,沒有萬用字元。

例如

$ mkdir /tmp/test
$ cd /tmp/test
$ echo rsync --exclude=*.{jpg,mp4}
rsync --exclude=*.jpg --exclude=*.mp4

到目前為止,一切都很好……但是看看當有文件名實際上匹配大括號擴展時會發生什麼:

$ touch -- --exclude=foo.jpg
$ touch -- --exclude=bar.mp4
$ touch -- --exclude=foobar.mp4
$ echo rsync --exclude=*.{jpg,mp4}
rsync --exclude=foo.jpg --exclude=bar.mp4 --exclude=foobar.mp4

避免輸入大量--exclude選項的更好方法是使用數組和 printf:

excludes=('*.mp4' '*.jpg')
rsync ...args... $([ "${#excludes[@]}" -gt 0 ] && printf -- "--exclude='%s' " "${excludes[@]}") ...more args...

這將導致如下命令行:

rsync ...args... --exclude='*.mp4' --exclude='*.jpg'  ...more args...

更好的是使用數組和程序替換來為--exclude-from. 例如

rsync ... --exclude-from=<([ "${#excludes[@]}" -gt 0 ] && printf -- '- %s\n' "${excludes[@]}") ... 

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