【cpコマンド】ファイル・ディレクトリをコピーする方法と主要オプション

実務レシピ

LinuxやUNIX系OSでファイルやディレクトリをコピーする際に使用する cpコマンド(copy)。基本的なファイルの複製から、ディレクトリの丸ごとバックアップまで、日常的に頻繁に使用されるコマンドです。

この記事では、cpコマンドの基本的な使い方から、-r-a といった主要オプションの違い、上書き時の注意点まで、コピペで使える実例とともにわかりやすく解説します。

cpコマンドの基本(単一・複数ファイルのコピー)

まずは、最も基本的なファイルのコピー方法です。ディレクトリ(フォルダ)をコピーする場合はオプションが必要ですが、通常のファイルコピーであればオプションなしで実行できます。

単一ファイルのコピー

cp コピー元 コピー先 の形式で指定します。

# file1.txt を file2.txt という名前でコピーする
$ cp file1.txt file2.txt

複数ファイルをディレクトリへコピー

複数のファイルをまとめて特定のディレクトリ(フォルダ)にコピーする場合は、末尾にコピー先のディレクトリを指定します。

# 複数のファイルを backup/ ディレクトリへコピー
$ cp file1.txt file2.txt backup/

# ワイルドカードを使って .txt ファイルを全てコピー
$ cp *.txt backup/

ディレクトリを丸ごとコピーする方法(-r / -a)

ディレクトリをコピーしようとして、オプションなしで実行すると cp: -r not specified; omitting directory とエラーになります。ディレクトリをコピーする場合は 再帰的コピー(recursive copy) のオプションが必須です。

目的おすすめのコマンド例特徴・用途
通常のディレクトリコピーcp -r src_dir/ dest_dir/中身を再帰的にコピー(階層ごと複製)
属性・タイムスタンプ保持cp -a src_dir/ dest_dir/バックアップ推奨。 所有者・権限・日時・リンクを保持
中身だけを直下へコピーcp -r src_dir/. dest_dir/コピー先の直下にファイル・隠しファイルを配置

-r と -a の違いと使い分け

実務やバックアップで特に重要なのが -r-a--archive)の使い分けです。

項目cp -r(通常再帰コピー)cp -a(アーカイブコピー)
パーミッション(権限)実行ユーザーの umask に応じて変更されるコピー元の権限を保持
タイムスタンプ(更新日時)コピーを実行した現在日時に更新されるコピー元の作成・更新日時を保持
シンボリックリンクリンクとして保持リンクとして保持(実体展開しない)
所有者・グループコピーを実行したユーザーになる元の所有者・グループを保持(要root権限)
推奨用途一時的なフォルダ複製、作業用ディレクトリ作成設定ファイル・システムバックアップ、データ移行
# 日時や権限を変えたくないバックアップには -a を使用
$ cp -a /etc/nginx/ /backup/nginx_conf_$(date +%Y%m%d)/

よく使う主要オプション一覧と安全な上書き対策

cp コマンドはデフォルトで 確認なしでファイルを上書き します。誤操作を防ぐためのオプション(-i など)を活用しましょう。

オプション意味・動作実務でのポイント
-r / -Rディレクトリを再帰的にコピーディレクトリ指定時に必須
-a (--archive)属性・リンク・時間を保持して再帰コピーバックアップ・データ移行の基本
-p (--preserve)ファイルの属性(権限・時間など)を保持-a よりも細かく保持内容を指定可能
-i (--interactive)同名ファイルが存在する場合、上書き確認を求める誤操作防止。キーボードの y / n で選択
-n (--no-clobber)既存ファイルを上書きせずスキップする既存データを保護しながら新規ファイルのみ追加
-f (--force)書き込み権限のない既存ターゲットファイルを削除して複製書込不可ファイルを強制作り直し(条件あり)
-u (--update)コピー元がコピー先より新しい場合のみ上書き簡易的な差分アップデート
-v (--verbose)コピーされたファイル名を順番に表示進捗状況の可視化やログ取得に有効

安全のために alias(エイリアス)を設定する

誤って重要なファイルを上書きしてしまわないよう、.bashrc などにエイリアスを設定し、常に -i オプションが有効になるようにしているユーザーも多くいます。

# ~/.bashrc に以下を追記
alias cp='cp -i'

コピー先の「存在有無」による構造の違い(実行前後のツリー比較)

cp -r で最も意図しないトラブルが起こりやすいのが、コピー先ディレクトリが事前に存在するかどうかによって生成されるディレクトリ階層が変わる点です。

ケース1:コピー先が存在しない場合(新規作成される)

dest_dir が存在しない状態で cp -r src_dir dest_dir を実行すると、dest_dir という名前で新規ディレクトリが作成され、その中に src_dir の中身が直接配置されます。

# コマンド実行(dest_dir は未存在)
$ cp -r src_dir dest_dir

# 実行後:dest_dir が作成され中身が直接入る
.
├── src_dir/
│   └── index.js
└── dest_dir/            ← 新しく作成された
    └── index.js

ケース2:コピー先が既に存在する場合(サブディレクトリとして入れ子になる)

すでに dest_dir が存在する状態で cp -r src_dir dest_dir/ を実行すると、dest_dir の中に src_dir ディレクトリ自体がコピーされ、二重階層(入れ子構造)になります。

# コマンド実行(dest_dir は既に存在)
$ cp -r src_dir dest_dir/

# 実行後:dest_dir の中に src_dir 自体が入る
.
├── src_dir/
│   └── index.js
└── dest_dir/
    └── src_dir/         ← サブディレクトリとして丸ごと入る
        └── index.js

ケース3:コピー先が存在し「中身だけ」を直下に配置したい場合

すでに存在する dest_dir の直下に src_dir の中身(隠しファイル含む)を直接コピーしたい場合は、コピー元に .(ドット) を付けます。

# コマンド実行(. を使用)
$ cp -r src_dir/. dest_dir/

隠しファイル・シンボリックリンク・末尾スラッシュの検証

1. 隠しファイル(.env や .gitignore)を含める方法

シェルでワイルドカード * を使用して cp -r src_dir/* dest_dir/ を実行すると、.env.gitignore などのドットから始まる隠しファイルが対象から漏れてしまいます。

# ❌ 隠しファイルがコピーされない危険な例
$ cp -r src_dir/* dest_dir/

# ✅ 隠しファイルも含めてディレクトリごとコピー
$ cp -r src_dir dest_dir/

# ✅ 既存ディレクトリの直下に隠しファイルも含めて中身をコピー
$ cp -r src_dir/. dest_dir/

2. シンボリックリンクの扱い(-r / -a / -L)

ディレクトリ内にシンボリックリンクが含まれている場合、デフォルト(-r-a)では シンボリックリンク自体がそのまま保持 されてコピーされます。リンク先の実体を展開してコピーしたい場合は -L--dereference を付与します。

# デフォルト(-r または -a):シンボリックリンクのままコピー
$ cp -r src_dir/ backup/

# 実体ファイルをコピーしたい場合:-L を追加
$ cp -rL src_dir/ backup/

Permission denied エラーの原因と対処法

cp コマンド実行時に Permission denied エラーが発生する場合、主に2つの原因が考えられます。

原因A:コピー先の「ファイル」に書き込み権限がない場合

コピー先ディレクトリには書き込み権限があるが、既に存在するコピー先ファイルが読み取り専用の場合です。この場合は -f オプション で強制的に上書き(削除して再作成)できます。

# -f オプションで既存の読み取り専用ファイルを削除して再作成
$ cp -f main.c /backup/main.c

原因B:コピー先の「ディレクトリ」自体に書き込み権限がない場合

/var/www/ など、管理者(root)権限が必要なディレクトリにコピーしようとしている場合、-f を付けてもエラーになります。sudo を付けて実行するか、コピー先ディレクトリの権限を変更します。

# 対処法:sudo を付けて管理者権限で実行する
$ sudo cp -r src_dir /var/www/html/

大量コピー・差分同期なら rsync コマンド

日常的なファイル操作や小規模な複製には cp で十分ですが、以下のようなケースでは rsync コマンド を利用するのが適切です。

  • 差分コピー: 変更があったファイルのみ転送し、高速に同期したい
  • 中断と再開: 途中で失敗した場合に、途中から再開(レジューム)したい
  • 進捗表示: リアルタイムな転送率や進捗バーを表示したい
  • ネットワーク転送: SSH経由でリモートサーバーと同期したい
# rsyncを使った高速なアーカイブ同期の例
$ rsync -av --progress src_dir/ /backup/src_dir/

まとめ

cpコマンドを使ったファイルやディレクトリのコピーについて解説しました。

  • ファイルコピー: cp file1 file2(オプション不要)
  • ディレクトリ複製: cp -r src_dir/ dest_dir/
  • バックアップ用途: 権限や日時を保持する cp -a
  • 上書き事故防止: -i(確認)や -n(スキップ)を活用する

特にディレクトリをコピーする場合は、コピー先の存在有無によって作られるディレクトリ構造が変わる点に注意してください。目的に応じた適切なオプションを選んで、安全にファイル操作を行いましょう。

関連記事:ファイル・ディレクトリ操作の基本コマンド

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする