rsyncは、ディレクトリを同期するのによく使います。しかし、ファイルパスの書き方でときどき混乱します。

混乱するのは、パス末尾のスラッシュの有無で挙動が変わるからです。

というわけで、同期するときのパスの書き方を整理してみました。

まずは理屈はさておき、ディレクトリを同期する構文としては、次の構文を暗記しておけば、いいでしょう(オプション-avは基本的な設定ですので、もう少し必要ですがここでは触れません)。

 rsync -av SRC/PATH/ DEST/PATH/

で、この構文は、このように理解しておけばいいのです。

 rsync -av ${どのファイル/ディレクトリを} ${どこへ置くか}

今まで混乱したのは、次のように考えていたからですが、これが間違いのもとでした。

NG: rsync -av ${同期したいディレクトリA} ${同期したいディレクトリB} 

正しくは、次の2パターンで考えます。

OK: rsync -av ${同期したいディレクトリAの中身} ${どこへ置くか}

OK: rsync -av ${同期したいディレクトリA} ${どこへ置くか}

送信元の書き方に、2パターンあるわけです。それぞれを構文的に書けば、次のようになります。

rsync -av /SRC/A/ /DEST/B/

rsync -av /SRC/A /DEST/

微妙の差なので、わかりにくいですが、スラッシュの有無に注意してください。

それではそれぞれのパターンについて説明します。

スラッシュあり:rsync -av /SRC/A/ /DEST/B/

まずはスラッシュが末尾にある/SRC/A/のパターンです。/SRC/A/はディレクトリAの中身を表わします。

したがって、この例では、”ディレクトリAの中身をどこへ置くか?”と考えて、受信先のパスを選びます。

今回の例では、ディレクトリBのなかへ置きたいわけですから、/DEST/B/と指定しています。

ちなみに、受信先の/DEST/B/は、スラッシュを省略して/DEST/Bと書いても同じです。今回はディレクトリであることを明示したいのでつけています。

この構文では、ディレクトリの中身を操作しているイメージです。

スラッシュなし:rsync -av /SRC/A /DEST/

一方、スラッシュなしで/SRC/Aと指定した場合、ディレクトリA本体を表わします。

したがって、この場合は、”ディレクトリAをどこへ置くのか?”と考えて、受信先のパスを選べばいいわけです。

ここでディレクトリAを置きたいのは/DEST/です。だからそのように指定しています。

このように、この構文はディレクトリ本体を操作しているイメージです。

まとめ

以上、2パターンの結果は同じなのですが、送信元のスラッシュ有無という小さな違いが、操作する対象とパスの書き方に違いがあります。

  • 送信元の末尾/有無の違い
  • 受信先の末尾/有無はどちらもでいい

最後に、ありがちな間違った例をあげておきます。

$ rsync -av /SRC/A /DEST/B
# NG: "ディレクトリA本体"がディレクトリBのなかにコピーされます

$ rsync -av /SRC/A/ /DEST/
# NG: "ディレクトリAの中身"が親ディレクトリにコピーされます

以上、参考になりましたら幸いです。

(追記)

あとで気付いたのですが、そもそもcpコマンドも同じような仕様っぽいのですね。cp /dir/sub /other/みたいな使い方しかしなかったので、気付いてませんでした(汗)。