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】接続エラーで停止する転送を自動でリトライする