まくろぐ

rsync コマンドで2つのディレクトリを同期する

更新:
作成:
Linux に付属されている rsync コマンドを使用すると、2つのディレクトリの内容(ファイル)を効率よく同期させることができます。SSH 経由でのリモートホストへのコピーにも対応しています。

(Windows の場合は、WinSCP をコマンドラインで利用すると同じようなことを実現できます)。

rsync でディレクトリごとコピーする

rsync コマンドを使って、src ディレクトリの内容を dst ディレクトリにコピーするには下記のように実行します。

例: src ディレクトリを dst ディレクトリにコピー
$ rsync -av src/ dst    # src ディレクトリの「中身」を dst ディレクトリ内へコピー
$ rsync -av src dst     # src ディレクトリを dst ディレクトリ内へコピー

-a オプションは、パーミッションやタイムスタンプなどの情報を維持しつつ、ディレクトリを再帰的にコピーする指定をまとめて行うための archive オプションです。 -v オプションは転送情報などを出力する verbose オプションです。

上記例のように、ソースディレクトリの最後にスラッシュをつけるかつけないかで意味が変わってくるので注意してください。 2番目のように実行すると、結果として ./dst/src というディレクトリが作成されることになります。

コピー元にないファイルを削除する (–delete)

rsync コマンドはデフォルトでは、コピー先ディレクトリのファイルを削除することはありません。 コピー元 (src) に存在しないファイルを、コピー先 (dst) から削除したいときは、明示的に --delete オプションを付けて実行します。 つまり、2つのディレクトリを同じ内容にしたい(同期したい)のであれば、--delete オプションを付けて実行する必要があります。

例: src の内容を dst に同期させる(src に存在しないファイルは dst から削除する)
$ rsync -av --delete src/ dst

指定した拡張子のファイルだけコピーする (–include)

特定の種類のファイル(png ファイルなど)だけをコピーしたいときは、--include オプションと --exclude を組み合わせて以下のような感じで指定します。

例: src 内の *.png を dst 以下にコピー
$ rsync -av --include='*.png' --include='*/' --exclude='*' src/ dst

この指定方法は少しわかりにくいので、実際にファイルコピーする前に、-n (--dry-run) オプションを付けて実行して、どのようなファイルがコピーされるのかを確認するとよいです。

rsync でリモートホストへディレクトリをコピーする

rsync コマンドは、リモートホストへのファイルコピーにも対応しています(デフォルトで SSH によるファイルコピーが行われます)。 リモートへのファイルコピーを指示したいときは、ターゲットディレクトリの部分を user@hostname:directory というフォーマットで指定します。 ディレクトリ名の部分を省略すると、指定したユーザ (user) のホームディレクトリがコピー先ディレクトリとして使用されます(この場合も、コロン : は省略できません)。

例: リモートホストのホームディレクトリにコピーする
$ rsync -rv --delete src user@example.com:

上記のようにすると、ローカルディレクトリ (src) の中のファイルが、リモートホスト (example.com) のユーザ (user) のホームディレクトリにコピーされます。 末尾のコロン (:) を忘れないように注意してください。 これを忘れると、ローカルに user@example.com という名前のディレクトリができてしまいます。

例: リモートホストのコピー先ディレクトリを指定してコピーする
$ rsync -rv --delete src/ user@example.com:dst

上記のようにすると、ローカルの src ディレクトリの中身が、リモートの dst ディレクトリにコピーされます。 src の後ろにバックスラッシュ (/) を忘れないように注意してください。 これを忘れると、リモートの dst ディレクトリの下に src ディレクトリができてしまいます。

例: 複数のディレクトリをまとめてコピーする
$ rsync -rv --delete src1 src2 src3 user@example.com:dst

上記のようにすると、ローカルの src1src2src3 ディレクトリを、リモートの ~/dst ディレクトリへコピーします。 コピー元のディレクトリ名の末尾にスラッシュ (/) を付けずに実行しているので、リモートの ~/dst ディレクトリ内に src1src2src3 ディレクトリがそれぞれ作成されます(ディレクトリ内のファイルがコピーされるのではなく、ディレクトリごとコピーされる)。

シンボリックリンク先の実体をコピーする(-L オプション)

例えば、次のように他のディレクトリへのシンボリックリンクを含む ~/src 以下のファイル群を ~/dst 以下に同期させたいとします。

~/src
  +-- sample.txt
  +-- data/ (~/real-data ディレクトリへのシンボリックリンク)

~/src/data というシンボリックリンクは、例えば ln -s ~/real-data ~/src/data のように作成したもので、実体となる ~/real-data ディレクトリの内容は次のような内容になっています。

~/real-data
   +-- images/
         +-- a.png
         +-- b.png
         +-- c.png

このような構成で ~/src ディレクトリ以下の内容を ~/dst ディレクトリ以下にシンクしてみます(src 自身をコピーしないために src/ のように末尾にスラッシュを忘れずに)。

$ rsync -a ~/src/ ~/dst

すると、デフォルトでは、~/dst の下にシンボリックリンクファイル (data) がそのままコピーされます。

$ ls -Fl ~/src
...省略... data@ -> /Users/maku/real-data
...省略... sample.txt

そうではなくて、リンク先のファイル群の実体をコピーしたいときは、rsync-L (--copy-links) オプション (transform symlink into referent file/dir) を指定します。

$ rsync -aL ~/src/ ~/dst

これで、~/dst/data はシンボリックリンクではなく、~/real-data 以下の内容がすべてコピーされたディレクトリになります。

$ ls -Fl ~/dst
...省略... data/  (通常のディレクトリで、a.png などが含まれている)
...省略... sample.txt

関連記事

まくろぐ
サイトマップまくへのメッセージ