Edited at

cp -r でのシンボリックリンクとハードリンクの扱い

More than 3 years have passed since last update.


シンボリックリンク

BSD UNIX や UNIX SVR4 などの伝統的な UNIX では cp -r でディレクトリをコピーした場合、ディレクトリツリーに含まれるシンボリックリンクは、シンボリックリンクがポイントするディレクトリやファイルを参照して、実体としてコピーされます。

Linux では cp -r でディレクトリをコピーした場合、ディレクトリツリーに含まれるシンボリックリンクは、シンボリックリンクとしてそのままコピーされます。これは、Linux では cp は GNU 版であり、GNU の拡張が入っているためです。

-p オプションの指定がなければ実体に置き換わるものだと思っていたら、シンボリックリンクのままだったので、うっかりハマりました。

ちなみに Linux でも cp シンボリックリンク 対象 というように -r オプションをつけない場合は、シンボリックリンクがポイントするディレクトリやファイルを参照して、実体としてコピーされます。


ハードリンク

ディレクトリツリー中にハードリンクが存在した場合、そのままではハードリンクが切れて、別々のファイルとしてコピーされてしまいます。Linux (GNU cp)の場合は、-d オプションを指定することでハードリンクを維持することができます。-d オプションは --no-dereference --preserve=links と同じです。また -a オプション(-dr --preserve=all と同じ)を指定すると、ハードリンクのほかに、対象ファイルやディレクトリのアクセスモードや所有者情報、タイムスタンプなどを維持してコピーしてくれます。

Solaris, FreeBSD, MacOS などでは、cp コマンドでハードリンクを維持したままディレクトリをコピーすることはできません。rsync -aHfind . -depth -print | cpio -pdmu コピー先 などの方法を使いましょう。

Solaris で tar コマンドを使用する場合、tar コマンドは 伝統的な UNIX と同様にパス名に 256 文字の制限があるため E オプションを指定する必要があります。