Bash
rsync:如何排除多種文件類型?
這是在執行 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
,但請注意:
- 這是一個稱為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[@]}") ...