cpコマンドの使い方:ファイル・ディレクトリのコピー完全ガイド

概要

cp(Copy)コマンドは、ファイルやディレクトリをコピーするための基本コマンドです。

現場での重要性: バックアップ作成、設定ファイルの退避、デプロイ前のファイル配置など、あらゆる運用作業で必須です。適切なオプションを知らないと、ディレクトリ構造を維持できなかったり、シンボリックリンクが意図せず実体ファイルに変換されたり、上書き確認なしに重要なファイルを消してしまうリスクがあります。逆に、cpの高度な使い方を習得することで、バックアップやデプロイ作業の効率が飛躍的に向上します。


基本コマンド・構文

最も基本的な使い方

cp source_file destination_file

実行例:

$ ls
config.ini

$ cp config.ini config.ini.bak
$ ls
config.ini  config.ini.bak

config.iniのコピーがconfig.ini.bakとして作成されます。

別のディレクトリにコピー

cp file.txt /path/to/destination/

実行例:

$ cp report.txt /backup/
$ ls /backup/
report.txt

現場で必須のオプション・設定

1. cp -r または cp -R:ディレクトリを再帰的にコピー

cp -r source_directory destination_directory

実行例:

$ ls myapp
config/  logs/  src/

$ cp -r myapp myapp_backup
$ ls
myapp  myapp_backup

$ ls myapp_backup
config/  logs/  src/

実務での活用理由: アプリケーションのディレクトリツリー全体をバックアップする際、サブディレクトリを含めてすべてコピーする必要があります。-rオプションなしでディレクトリをコピーしようとすると、エラーになります。デプロイ前の環境バックアップや、開発環境の複製で多用します。

2. cp -p:タイムスタンプと権限を保持してコピー

cp -p file.txt /backup/

実行例:

$ ls -l config.ini
-rw-r--r-- 1 user user 1234 Jan 25 10:30 config.ini

$ cp -p config.ini /backup/
$ ls -l /backup/config.ini
-rw-r--r-- 1 user user 1234 Jan 25 10:30 /backup/config.ini

実務での活用理由: バックアップやアーカイブ作成時に、元のファイルのタイムスタンプ、所有者、権限をそのまま保持する必要がある場合に使用します。ログファイルのバックアップや、本番環境のファイルを開発環境に複製する際、元のメタデータを維持することで、問題の追跡がしやすくなります。

3. cp -i:上書き前に確認

cp -i file.txt /path/to/destination/

実行例:

$ cp -i config.ini /backup/
cp: overwrite '/backup/config.ini'? y

実務での活用理由: 既に存在するファイルを誤って上書きしてしまうことを防ぎます。本番環境での作業や、重要な設定ファイルを扱う際は必須です。エイリアスでcpcp -iに設定しておくことを推奨します。

# .bashrc に追記
alias cp='cp -i'

4. cp -a:アーカイブモード(-dR --preserve=all と同等)

cp -a source_directory destination_directory

実行例:

$ cp -a /var/www/myapp /backup/myapp_$(date +%Y%m%d)
$ ls -la /backup/myapp_20260130
total 12
drwxr-xr-x 3 www-data www-data 4096 Jan 29 10:30 .
drwxr-xr-x 5 root     root     4096 Jan 30 11:00 ..
drwxr-xr-x 2 www-data www-data 4096 Jan 29 10:30 config

実務での活用理由: ディレクトリ構造、権限、所有者、タイムスタンプ、シンボリックリンクをすべて保持したまま完全なコピーを作成します。本番環境のバックアップや、システム全体の複製で使用します。-a-dR --preserve=allの短縮形で、最も包括的なコピーオプションです。

5. cp -u:更新されたファイルのみコピー

cp -u source/* destination/

実行例:

$ ls -l source/
-rw-r--r-- 1 user user 1234 Jan 30 10:00 file1.txt
-rw-r--r-- 1 user user 5678 Jan 30 11:00 file2.txt

$ ls -l destination/
-rw-r--r-- 1 user user 1234 Jan 30 10:00 file1.txt
-rw-r--r-- 1 user user 5678 Jan 29 09:00 file2.txt

$ cp -u source/* destination/
# file2.txt のみコピーされる(file1.txt は同じタイムスタンプなので無視)

実務での活用理由: 大量のファイルを定期的に同期する際、変更されたファイルだけをコピーすることで、処理時間を大幅に短縮できます。ただし、完全な同期にはrsyncの方が適しています。


実践的なユースケース(逆引きレシピ)

ケース1:バックアップを日付付きで作成

設定ファイルのバックアップを日付付きで保存:

cp config.ini config.ini.$(date +%Y%m%d_%H%M%S)

実行例:

$ cp config.ini config.ini.$(date +%Y%m%d_%H%M%S)
$ ls
config.ini  config.ini.20260130_110530

ケース2:ディレクトリ全体をアーカイブとして完全にバックアップ

本番環境のアプリケーションディレクトリを完全にバックアップ:

cp -a /var/www/myapp /backup/myapp_$(date +%Y%m%d)

実行例:

$ cp -a /var/www/myapp /backup/myapp_20260130
$ ls -la /backup/myapp_20260130
# 権限、所有者、タイムスタンプがすべて保持される

ケース3:複数のファイルを一度にコピー

複数の設定ファイルをバックアップディレクトリにコピー:

cp file1.txt file2.txt file3.txt /backup/

実行例:

$ cp config.ini settings.yaml app.conf /backup/
$ ls /backup/
config.ini  settings.yaml  app.conf

ケース4:ワイルドカードで特定の拡張子のファイルをコピー

ログファイル(.log)だけをバックアップ:

cp /var/log/myapp/*.log /backup/logs/

実行例:

$ cp /var/log/myapp/*.log /backup/logs/
$ ls /backup/logs/
access.log  error.log  debug.log

ケース5:シンボリックリンクを実体ファイルに変換してコピー

シンボリックリンクをリンク先の実ファイルとしてコピー(デフォルト動作):

$ ls -l
lrwxrwxrwx 1 user user 10 Jan 30 11:10 link.txt -> file.txt
-rw-r--r-- 1 user user 1234 Jan 30 11:10 file.txt

$ cp link.txt copy.txt
$ ls -l copy.txt
-rw-r--r-- 1 user user 1234 Jan 30 11:15 copy.txt
# リンクではなく実ファイルとしてコピーされる

シンボリックリンクをリンクのままコピーする場合は-dオプション(または-a)を使用:

$ cp -d link.txt copy_link.txt
$ ls -l copy_link.txt
lrwxrwxrwx 1 user user 10 Jan 30 11:20 copy_link.txt -> file.txt

シニアエンジニアの知恵(Expert Advice)

1. cp ではなく rsync を検討すべき場面

大規模なディレクトリ同期や、ネットワーク経由のコピーでは、rsyncの方が効率的です。

# rsync の方が適している例
rsync -av --delete source/ destination/

rsyncは差分転送、帯域制限、除外パターンなど、高度な機能を持っています。

2. -i オプションをデフォルトにする

誤った上書きを防ぐため、エイリアスでcp -iを設定してください。

# .bashrc または .zshrc に追記
alias cp='cp -i'

ただし、スクリプト内では\cpでエイリアスを無効化できます。

\cp file.txt /backup/  # エイリアスを無視

3. ディレクトリコピー時の末尾スラッシュに注意

コピー先のパス指定で、末尾に/があるかないかで挙動が変わります。

# destination/ が存在する場合
cp -r source destination/
# 結果: destination/source/ が作成される

cp -r source destination
# 結果: destination が source の内容で上書きされる(または新規作成)

意図しない動作を防ぐため、コピー先のパスは明示的に指定してください。

4. ハードリンクを使ったスペース節約

同じファイルを複数の場所に配置する際、実体をコピーせずハードリンクを作成:

cp -l source.txt destination.txt

ただし、ハードリンクは同じファイルシステム内でのみ有効で、一方を編集すると他方も変更されます。バックアップには不向きです。

5. コピー元とコピー先の権限の違いに注意

cpでファイルをコピーすると、デフォルトではumaskに従った権限が設定されます。元の権限を保持する場合は-pまたは-aオプションを使用してください。

# 権限が変わる例
$ ls -l source.txt
-rwxr-xr-x 1 user user 1234 Jan 30 11:30 source.txt

$ cp source.txt destination.txt
$ ls -l destination.txt
-rw-r--r-- 1 user user 1234 Jan 30 11:31 destination.txt

# 権限を保持する
$ cp -p source.txt destination.txt
$ ls -l destination.txt
-rwxr-xr-x 1 user user 1234 Jan 30 11:30 destination.txt

6. 本番環境でのコピー前の確認

本番環境で重要なファイルをコピーする前に、必ず以下を確認してください:

  1. コピー先のディスク容量が十分か(df -h
  2. コピー元のファイルが正しいか(ls -l
  3. 上書きするファイルのバックアップがあるか
# 容量確認
df -h /backup

# コピー前の確認
ls -lh source_file

# バックアップを取ってからコピー
cp -p important_file important_file.bak.$(date +%Y%m%d)
cp -i source_file important_file

7. スクリプト内でのエラーハンドリング

cpが失敗した場合の処理を必ず組み込んでください。

#!/bin/bash

cp -a /var/www/myapp /backup/myapp || {
  echo "バックアップに失敗しました"
  exit 1
}

echo "バックアップが完了しました"

または、set -eでスクリプト全体をエラー時に停止させる設定を推奨します。