rsyncでコピーした後に、転送元と転送先が一致しているかを確認したい場合は、同じrsyncをドライラン(-n)で実行する。転送対象のファイルが1つもなければ、一致している。
$ rsync -rltnc -i src/ dst/
出力が空であれば、src/の内容がすべてdst/に存在して、ファイルの中身も一致している。差分があるファイルは、1行ずつ表示される。
$ rsync -rltnc -i src/ dst/
>fc........ rot.txt
>fcs....... size.txt
>f+++++++++ sub/missing.txt
実行例はrsync 3.5.1、macOS 27.0.1のもの。コピー元をsrc/、コピー先をdst/とする。
オプションの意味
| オプション | 意味 |
|---|---|
-n | ドライラン。ファイルを転送せずに、転送する予定の内容だけを表示する |
-c | 更新時刻とサイズではなく、チェックサム(ファイルの中身)で比較する |
-i | ファイルごとに、差分の内容を示す記号を表示する(--itemize-changes) |
-rlt | コピーしたときと同じオプションを指定する。ここでは再帰、シンボリックリンクの保持、更新時刻の保持 |
コピーしたときのオプションと、比較の条件を合わせる。--excludeや--no-permsなどをコピーのときに指定した場合は、検証でも同じ指定を付ける。条件が違うと、実際には問題のないファイルが差分として表示される。
-cが必要な理由
-cを付けないrsyncは、ファイルのサイズと更新時刻が一致すれば、同じファイルとみなす。中身が破損していても、サイズと更新時刻が同じなら、差分として検出されない。
サイズと更新時刻は同じで、中身だけが異なるファイルを用意して、-cの有無を比較した。
$ printf 'hello world' > src/rot.txt
$ cp -p src/rot.txt dst/rot.txt
$ printf 'hellX world' > dst/rot.txt
$ touch -r src/rot.txt dst/rot.txt
$ rsync -rltn -i src/ dst/
$ rsync -rltnc -i src/ dst/
>fc........ rot.txt
-cなしでは、rot.txtは何も表示されない。-cを付けると、c(チェックサムの差分)として検出される。
-cは、転送元と転送先のすべてのファイルを読み込んで、チェックサムを計算する。ファイルの量が多いと、時間がかかる。ネットワーク越しの共有では、すべてのファイルの内容をネットワーク経由で読み込む。
コピーのときに--size-onlyを指定した場合は、サイズだけで比較しているため、中身の確認が済んでいない。検証では-cを付けるとよい。
差分の記号の見方
-iは、先頭の11文字で差分の内容を表す。
>fcs....... size.txt
先頭の2文字は、転送の方向とファイルの種類である。>fは、転送元から転送先へ送信する通常のファイルを表す。3文字目以降には、差分のある属性を示す記号が並ぶ。
| 表示 | 意味 | 例 |
|---|---|---|
>f+++++++++ | 転送先にファイルがない | sub/missing.txt |
>f.s....... | サイズが異なる | |
>fc........ | チェックサムが異なる(-cの場合) | rot.txt |
>fcs....... | チェックサムとサイズの両方が異なる | size.txt |
>f..t...... | 更新時刻が異なる(-cなしの場合) |
-cを付けると、更新時刻だけが異なるファイルは、中身が一致するため、.f..t......と表示される。更新時刻の属性だけを更新する対象で、^>fでは絞り込まれない。
中身の差分があるファイルだけを取り出すには、^>fで絞り込む。
$ rsync -rltnc -i src/ dst/ | grep '^>f'
差分の件数を確認する
--statsを付けると、転送する予定のファイル数と、合計サイズを確認できる。
$ rsync -rltnc --stats src/ dst/ | grep -E 'Number of regular files transferred|Total transferred file size'
Number of regular files transferred: 3
Total transferred file size: 24 bytes
Number of regular files transferredが0であれば、差分はない。ドライランでも、転送する予定のファイル数が表示される。
スクリプトで判定するときは、終了コードでなく出力を確認する。ドライランは、差分があっても、終了コード0で終了する。
$ rsync -rltnc src/ dst/ > /dev/null
$ echo $?
0
if [[ -z $(rsync -rltnc -i src/ dst/ | grep '^>f') ]]; then
echo "OK: no differences"
else
echo "NG: differences found"
fi
転送先だけにあるファイルを調べる
--deleteを付けると、転送先だけにあるファイルを、*deletingとして表示できる。
$ rsync -rltnc -i --delete src/ dst/ | grep deleting
*deleting extra.txt
--deleteは、-nなしで実行すると、転送先だけにあるファイルを削除する。コピーのときは付けない。確認のときも、-nの付け忘れに注意する。-rltncのように、-nをオプションにまとめておくと、付け忘れを防げる。
差分があったファイルを再コピーする
差分が表示されたファイルは、-nを外して実行すれば、転送し直せる。-cを付けたままにすると、中身が異なるファイルだけが再転送される。
$ rsync -rltc src/ dst/
参考: 【rsync】接続エラーで停止する転送を自動でリトライする
