Linuxのコマンドライン操作において、ディレクトリのコピーは基本中の基本と言える操作です。
しかし、オプションの指定を誤ると、予期せぬ権限エラーやリンクの破損を招くことがあります。
日常的にBashを利用していても、「-r」と「-a」の明確な違いを説明できる方は意外と少ないかもしれません。
特にシステム管理やデプロイ作業を行う際には、これらの違いが致命的な影響を与えることもあります。
本記事では、cp -rとcp -aの挙動の差を詳細に整理し、どのような場面でどちらを使うべきかを解説します。
cpコマンドにおけるディレクトリコピーの基本
cpコマンドは、ファイルやディレクトリを複製するために使用されます。
通常、ファイルのみをコピーする場合はオプションなしで実行可能です。
しかし、ディレクトリをコピーしようとすると、デフォルトではエラーが表示されます。
# ディレクトリをそのままコピーしようとするとエラーになる
cp source_directory destination_directory
cp: -r not specified; omitting directory 'source_directory'
このエラーを回避し、ディレクトリの中身を再帰的にコピーするために導入されるのが-rや-aといったオプションです。
-r(recursive)オプションの役割
-rは「recursive(再帰的)」の略称です。
このオプションを指定すると、指定したディレクトリ配下にあるすべてのファイルとサブディレクトリをコピー対象に含めます。
最も一般的で、単純なディレクトリコピーによく使われるオプションです。
ただし、-rはあくまで「再帰的にコピーする」という点に特化しています。
そのため、コピー後のファイル属性が元のファイルと異なってしまう場合があることに注意が必要です。
-a(archive)オプションの役割
-aは「archive(アーカイブ)」の略称です。
このオプションは、単にディレクトリをコピーするだけでなく、元の状態をできる限り保持したまま複製することを目的としています。
内部的には、いくつかの主要なオプションを組み合わせたショートカットとして機能します。
具体的には、-d、-p、-Rの3つのオプションを同時に指定したのと同等の効果があります。
「元の構成や権限を完全に再現したい」という場合には、この-aが推奨されます。
-rと-aの決定的な違い
これら二つの最大の違いは、コピーされたデータの「メタ情報」の扱いにあります。
ここでは、代表的な3つの違いについて深く掘り下げていきます。
1. ファイル属性の保持(Permission and Timestamps)
-rオプションでコピーを行った場合、コピー後のファイル属性は「コピーを実行した環境」に依存します。
例えば、タイムスタンプ(更新日時)はコピーを行った現在の時刻になります。
また、パーミッションや所有者情報も、実行ユーザーの設定に基づいて新しく生成されます。
対して、-aオプションを使用すると、元のファイルの更新日時、作成日時、アクセス権限、所有者情報が可能な限り引き継がれます。
これはバックアップ作業において非常に重要なポイントとなります。
2. シンボリックリンクの扱い
シンボリックリンクが含まれるディレクトリをコピーする際、挙動が大きく異なります。
-rオプションを使用すると、デフォルトではシンボリックリンクを「参照先の実体ファイル」としてコピーしようとします。
つまり、リンクではなく実際のファイルが複製されるため、ディスク容量を余計に消費する可能性があります。
一方で、-aオプションには-dオプション(リンクを維持する機能)が含まれています。
そのため、シンボリックリンクは「リンクのまま」コピー先に配置されます。
3. 特殊ファイルのコピー
Linuxシステムには、デバイスファイルや名前付きパイプといった特殊なファイルが存在します。
-rオプションでは、これらの特殊ファイルを正しくコピーできない場合があります。
-aオプションであれば、これらの特殊な属性を持つファイルも適切に再現されます。
システムディレクトリ(/etcや/varなど)を移行する際には、-aの利用が必須と言えるでしょう。
実行結果による比較検証
実際にそれぞれのオプションでどのような差が出るのかを確認してみましょう。
まずは、テスト用のディレクトリとシンボリックリンクを作成します。
# テスト環境の準備
mkdir original_dir
touch original_dir/file1.txt
ln -s file1.txt original_dir/link_to_file1
ls -l original_dir
total 0
-rw-r--r-- 1 user user 0 May 10 10:00 file1.txt
lrwxrwxrwx 1 user user 9 May 10 10:01 link_to_file1 -> file1.txt
cp -r を実行した場合
次に、-rオプションを使ってコピーを行います。
cp -r original_dir copy_r_dir
ls -l copy_r_dir
total 0
-rw-r--r-- 1 user user 0 May 20 15:00 file1.txt
-rw-r--r-- 1 user user 0 May 20 15:00 link_to_file1
注目すべきは、link_to_file1が通常のファイルとしてコピーされ、タイムスタンプが実行時刻に変わっている点です。
cp -a を実行した場合
続いて、-aオプションでコピーを行います。
cp -a original_dir copy_a_dir
ls -l copy_a_dir
total 0
-rw-r--r-- 1 user user 0 May 10 10:00 file1.txt
lrwxrwxrwx 1 user user 9 May 10 10:01 link_to_file1 -> file1.txt
タイムスタンプが保持され、シンボリックリンクもリンクの状態を維持していることが分かります。
どちらを使うべきか?使い分けの基準
状況に応じて適切なオプションを選択することが、トラブルを防ぐ鍵となります。
cp -r を推奨する場面
既存のファイルを雛形として使い、新しいプロジェクトを開始する場合などに適しています。
「中身のデータさえあればよく、過去の属性情報は不要」というケースでは、-rで十分です。
また、他人のファイルをコピーして自分の所有物にしたい場合も、-rを使う方が後々の権限トラブルを避けられます。
cp -a を推奨する場面
データのバックアップや、サーバー移転に伴うデータの移行作業では必ず-aを使用してください。
プログラムの実行ファイルやライブラリを含むディレクトリをコピーする場合も、-aが必要です。
「構造を壊さずにそのまま複製する」ことが求められるシーンでは、-aが唯一の選択肢となります。
比較表:cp -r vs cp -a
それぞれの違いをわかりやすく表にまとめました。
| 機能 | cp -r | cp -a |
|---|---|---|
| 再帰的コピー | 対応 | 対応 |
| 属性(権限等)の保持 | 保持しない | 保持する |
| タイムスタンプの保持 | 保持しない | 保持する |
| シンボリックリンクの扱い | 実体をコピー | リンクを維持 |
| 主な用途 | 単純な複製 | バックアップ・移行 |
知っておくと便利な補足オプション
-aオプション以外にも、属性保持に関連するオプションがいくつか存在します。
例えば、-pオプションは「preserve」の略で、所有者や権限、タイムスタンプを保持します。
-aを使うほどではないが、特定の属性だけは守りたいという場合に便利です。
また、コピーの進捗を確認したい場合は、-v(verbose)オプションを組み合わせるのが一般的です。
# 属性を保持しつつ、詳細を表示しながらコピー
cp -av source_dir destination_dir
このように、複数のオプションを組み合わせることで、より安全で確実な操作が可能になります。
まとめ
本記事では、Bashにおけるcp -rとcp -aの違いについて詳しく解説しました。
単にディレクトリを再帰的にコピーするだけであれば-rで事足ります。
しかし、パーミッションやタイムスタンプ、シンボリックリンクといったメタ情報を正確に維持したい場合は、必ず-aオプションを選択してください。
特にシステム運用やバックアップの現場では、この僅かな違いが結果に大きな差を生みます。
今後は、コピーの目的に応じてこれらのオプションを適切に使い分けていきましょう。
基本的なコマンドだからこそ、その詳細な挙動を理解しておくことがプロフェッショナルへの第一歩となります。
