2025年4月30日 星期三

rsync 能不覆蓋相同檔名的檔案嗎?還有注意事項

rsync 可以設定不覆蓋目標端已存在的檔案,即使檔名相同,方法如下:


使用 --ignore-existing 參數

rsync -av --ignore-existing source/ destination/

說明:

  • -a:archive 模式,保留權限、符號連結、時間等

  • -v:verbose,顯示處理過的檔案

  • --ignore-existing只傳送「目標端不存在」的檔案


範例說明

rsync -av --ignore-existing /mnt/usb/usr/ /usr/

 這會將 /mnt/usb/usr/ 的內容傳到 /usr/但若 /usr/ 裡已經有相同檔案(名稱相同),就不會覆蓋


 如果你想更進一步「比較時間戳」再決定是否要傳送:

rsync -av --update source/ destination/
  • --update:只有當 來源檔案比較新 時才會覆蓋目標端檔案。


注意事項:

  • --ignore-existing 不會刪除任何東西,但會略過覆蓋已存在的檔案。

  • 若要完全模擬(不實際執行),可以加 --dry-run

rsync -av --ignore-existing --dry-run source/ destination/


如果你想要「只略過同名 & 內容相同」的檔案?

那就要用:

rsync -a --checksum source/ destination/

--checksum 行為:

  • 會比對 檔案內容的 checksum

  • 如果內容一樣,即使修改時間不同也不傳送

  • 若內容不同,才會傳送(覆蓋)

但這會很慢,因為每個檔案都要計算 hash。

結論

  • 只複製目標端「不存在」的檔案 --ignore-existing
  • 比較「修改時間」,來源新才傳 --update
  • 比較「內容」,內容不同才覆蓋 --checksum


注意事項

rsync -avz --ignore-existing --rsync-path="sudo rsync" /home/user/myos/usr/include/* myID@192.168.1.25:/usr/include

行為:

將本地的 /usr/include 底下的檔案(從交叉編譯 sysroot)同步到遠端 RPi 的 /usr/include 使用 sudo rsync 讓目標端具備寫入權限 --ignore-existing 保護 RPi 上已有的檔案不被覆蓋

潛在問題與改進建議:

1. 使用萬用字元 * 會展開成平面路徑,可能導致錯誤

$RPI_ROOT_PATH/rpi-sysroot/usr/include/*

這會展開成:

/home/xxx/rpi-sysroot/usr/include/a.h /home/xxx/rpi-sysroot/usr/include/dir1 /home/xxx/rpi-sysroot/usr/include/dir2 ...

目標端會把它們都放進 /usr/include/,可能破壞原本結構

建議改法(保留原始結構):

rsync -avz --ignore-existing --rsync-path="sudo rsync" \

$RPI_ROOT_PATH/rpi-sysroot/usr/include/ \ $RPI_ID_DEF@$PI_ADDR_DEF:/usr/include/

注意結尾的 / → 表示同步目錄內容,而不是目錄本身

2. 確認遠端 sudo rsync 有權限覆寫 /usr/include

你應該在遠端 RPi 的 /etc/sudoers 中讓 rsync 可執行而不需要互動密碼,例如加一行(使用 visudo 編輯):

root ALL=(ALL) NOPASSWD: /usr/bin/rsync

或你是用 root 使用者登入,就不需要 sudo rsync


沒有留言:

張貼留言