ディレクトリをコピーするときの挙動

rsync は source の後ろにスラッシュを付けるかどうかで挙動が変わる。
すなわち rsync -a source destrsync -a source/ dest は違う。

  • 前者だと source を dest にコピーしてくるという意味になるので dest/source ディレクトリができる
  • 後者だと source の中身を dest にコピーしてくるという意味になるので dest ディレクトリの中身と source ディレクトリの中身を一致させるように上書きする

特定のファイルタイプだけ処理したいとき

例えば jpeg だけコピーしたいなら、オプションとして --include='*/' --include='*.jpg' --exclude='*' のようにする。

なぜ?

rsync の処理フィルタについて、

  • フィルタオプションは先につけたものが優先される。オプションを最初から順に見ていき、include オプションに先にマッチすると、そのディレクトリ・ファイルは処理が確定する。
  • rsync は処理するかの判定をディレクトリ構造を下りながら逐一行いディレクトリが exclude された時点でそのディレクトリ内のファイルはすべて処理しない

というルールがあるためである。
なので上のように書くことで

  1. あらゆるディレクトリは必ず include する
    • このフィルタを付けて初めて全ファイルが検索対象になる
  2. *.jpg は必ず include する
  3. それ以外のファイルは exclude する

となり、所望の動作が達成できる。
例えば、 example/dir/ というディレクトリの下に画像ファイルがある場合、

  • example/ はルール 1 にマッチ→処理対象
  • example/dir/ はルール 1 にマッチ→処理対象
  • example/dir/file.jpg はルール 2 にマッチ→処理対象
  • example/dir/file.png はルール 3 にマッチ→対象外

のようになる。
なお、対象のファイルがないディレクトリについてもルール 1 によりすべてコピーするため、空のディレクトリがたくさんコピーされてしまうがご愛敬。

参考記事

上の記述は rsync の複雑怪奇な exclude と include の適用手順を理解しよう - てっく煮ブログ を参考にした。ありがとうございます。

応用

シェルのブレース展開機能を使うと、--exclude={'*.jpg','*.png'} のようなオプションを付けることで複数のファイルタイプを一括で排除できる。

バックアップをとるとき

オプションとして -ahH --info=progress2 としておけばよい。

  • -a: -rlptgoD に等しい
    • recursive
    • copy symlinks as symlinks
    • preserve permissions
    • preserve modification times
    • preserve group
    • preserve owner
    • preserve device and special files
  • -h: numbers in human-readable format
  • -H: ハードリンクを保持

進行度を正確に把握したいとき

--no-inc-recursive とすると、転送前に一度すべてのファイルのスキャンを行い、総転送量を把握したうえで全体の進捗を正確に表示する。

通信・ファイルアクセスが遅いとき

  • -z: ファイルデータを圧縮
  • -W: 増分アルゴリズムなしで全体をコピーする。ネット接続よりディスクアクセスが遅いときに有効