manに「cp -rは使うな」と書いてあった話

cp -rでシンボリックリンクまで実体としてコピーされて困ったのでMacのmanを読んでいたのだが、そもそもcp -rってオプション一覧に載ってない。あれれ?と思って続きを読んでいたら互換性の章でstrongly discouragedと書かれていた。

COMPATIBILITY
Historic versions of the cp utility had a -r option. This implementation supports that option; however, its use is strongly discouraged,
as it does not correctly copy special files, symbolic links, or fifo's.

代わりに-Rを使うべきだそうだ。その場合のシンボリックリンクの扱いをどうするかはオプションで指定できて、デフォルトではno symbolic links are followed。

-P If the -R option is specified, no symbolic links are followed. This is the default.

この挙動はPOSIX.2準拠とのこと。

STANDARDS
The cp command is expected to be IEEE Std 1003.2 (``POSIX.2'') compatible.

追記(ささださんに色々教えてもらった)

POSIX の記述(SUSv4)

Earlier versions of this standard included support for the -r option to copy file hierarchies. The -r option is historical practice on BSD and BSD-derived systems. This option is no longer specified by POSIX.1-2008 but may be present in some implementations. The -R option was added as a close synonym to the -r option, selected for consistency with all other options in this volume of POSIX.1-2008 that do recursive directory descent.


POSIX.2 ってのはもう無いらしい

Q10. What is IEEE POSIX 1003.2 Shell and Utilities?

This standard defines a standard source level interface to the shell and utility functionality required by application programs, including shell scripts. This standard has been incorporated into the latest revision of POSIX 1003.1 and thus a POSIX.2 standard no longer exists.

http://www.opengroup.org/austin/papers/posix_faq.html/

追記(他のやり方など)

  • 「cp -a」派
    • ただしこれが実装されているかは環境依存(hiby: -a オプションが実装されてない UNIX OSも在るのですよ…)
  • 「tar cf | tar xf」派
    • tmatsuu: 俺はtar cf - hoge | tar xf -もよく使う。tar xpfでもok
    • terazzo: tar -C src -cf - .|tar -C dst -xvf - とか
    • dekaino: ふつー (cd [srcdir] ; tar cf - .) | (cd [destdir]; tar xf -) ですよねー
  • rsync」派
    • y-kawaz: そもそもファイルもディレクトリも cp -a 使ってるわ。もしくはタイムスタンプとかも保存したい時は -ap 。更に言うならローカルのコピーでも rsync -av 使うことも多い。
  • aliasしとけばええんや派
    • dankogai: alias cp "cp -ipRH" # -a が -pPR 相当

で、僕は結局「コピーしない対象を--excludeとかで指定したいんだがcpにそういうオプションが見つからない」という理由でrsyncを使いました。