cp コマンド

目次

概要

cp - ディレクトリやファイルをコピーする

コマンドライン

cp [OPTION]... [-T] SOURCE DEST
cp [OPTION]... SOURCE... DIRECTORY
cp [OPTION]... -t DIRECTORY SOURCE...

対象バージョン

説明

ファイルからファイルへのコピー

ファイルやディレクトリをコピーします。下記は fileA.txt ファイルを fileB.txt にコピーする例です。コピー先は無ければ作成され、あれば上書きされます。

$ cp fileA.txt fileB.txt

ファイルからディレクトリへのコピー

コピー先がすでに存在するディレクトリの場合、ディレクトリ配下にファイルをコピーします。コピー元ファイルは複数指定することができます。

$ mkdir backup
$ cp fileA.txt fileB.txt fileC.txt backup

ディレクトリからディレクトリへのコピー(-r)

コピー元がディレクトリの場合は -r オプションをつけます。コピー先ディレクトリが存在しない場合は作成され、存在する場合はその配下にコピーされます。

$ cp -r src-dir dst-dir

上書き確認(-i)

誤ってファイルを上書きしてしまうのを防ぐには -i オプションをつけます。ファイルを上書きする際に確認プロンプトが表示されます。

$ cp -i fileA fileB
cp: overwrite 'fileB'? y

常に確認付きで実行するために、.bashrc などに下記を追加することもあります。

alias cp='cp -i'

属性もコピーする(-p, -a)

通常のコピーは、ファイルの所有者やタイムスタンプなどが変更されますが、-p オプションをつけると所有者やタイムスタンプが維持されます。

$ cp -rp src backup

また、-a オプションをつけると、-p で維持されるものに加え、ハードリンクや SELinux のセキュリティ情報などもすべて維持されます。

$ cp -ra src backup

オプション

確認

-i, --interactive
コピー先ファイルを上書きする際に確認プロンプトを表示します。-n オプション指定時は無視されます。

階層構造の再帰コピー

-R, -r, --recursive
ディレクトリをコピーする際に指定します。ディレクトリの階層構造を再帰的にコピーします。
--parents
コピー元ファイルの親ディレクトリの階層構造を保ったままコピーします。下記の例で通常は httpd.confrootBackup の直下にコピーされますが、--parents を指定すると /etc/httpd/conf のディレクトリ階層構造を保ったままコピーされます。
$ mkdir ./rootBackup
$ cp --parents /etc/httpd/conf/httpd.conf ./rootBackup
$ find ./rootBackup -name "httpd.conf"
./rootBackup/etc/httpd/conf/httpd.conf

バックアップ

--backup[=CONTROL]
バックアップ先にすでに同名のファイルが存在する場合、古いファイルを末尾に ~ をつけてバックアップを残します。下記の例では2回バックアップを行っていますが、1回目のバックアップ時のファイルが fileA~ として残されています。
$ mkdir dirA                    # dirAを作成
$ echo "AAA" > dirA/fileA       # fileAを作成
$ cp -rT --backup dirA dirB     # 一度バックアップをとる
$ echo "AAAAA" > dirA/fileA     # fileAの中身を書き換える
$ cp -rT --backup dirA dirB     # 再度バックアップをとる
$ ls -l dirB
total 8
-rw-r--r-- 1 yamada yamada 6 Jul 14 22:51 fileA
-rw-r--r-- 1 yamada yamada 4 Jul 14 22:51 fileA~

CONTROL には下記のいずれかを指定します。

  • none : バックアップしません
  • simple : 末尾に ~ をつけます。2世代前のバックアップは削除されます
  • numbered : ~ の代わりに .~1~, .~2~ のような番号をつけます
  • existing : 既存バックアップに .~1~ 等があれば numbered、さもなくば simple で動作します
-b
--backup=existing と同等です。
-S, --suffix=SUFFIX
--backup オプションで作成するファイル末尾の ~ を別のサフィックスに変更します。--backup=numbered の場合はこのオプションを指定しても変更されません。
$ mkdir dirA
$ echo "AAA" > dirA/fileA
$ cp -rT --suffix=.bak dirA dirB
$ cp -rT --suffix=.bak dirA dirB
$ ls -l dirB/*
-rw-r--r-- 1 yamada yamada 4 Jul 15 01:05 fileA
-rw-r--r-- 1 yamada yamada 4 Jul 15 01:05 fileA.bak
-T, --no-target-directory
コピー先フォルダの有無によるコピー動作の差異を吸収します。下記が、コピー先(src.bak)の有無によりコピーの動作が変わってしまう例です。
$ mkdir src                 # srcディレクトリを作成
$ touch src/fileA.txt       # fileA.txtファイルを作成
$ cp -r src src.bak         # バックアップをコピーする
$ find ./src.bak            # バックアップが作成される
./src.bak
./src.bak/fileA.txt
$ cp -r src src.bak         # もう一度コピーする
$ find ./src.bak            # バックアップ先にsrcディレクトリができてしまった
./src.bak
./src.bak/src
./src.bak/src/fileA.txt
./src.bak/fileA.txt

-T オプションを指定することにより、常にコピー先が存在しない場合の動作に統一することができます。

$ mkdir src                 # srcディレクトリを作成
$ touch src/fileA.txt       # fileA.txtファイルを作成
$ cp -rT src src.bak        # バックアップをコピーする
$ cp -rT src src.bak        # もう一度コピーする
$ find ./src.bak            # バックアップ先にsrcは作成されない
./src.bak
./src.bak/fileA.txt
-l, --link
コピーする代わりにハードリンクを作成します。
$ touch fileA.txt
$ cp -l fileA.txt fileB.txt
$ ls -l *
-rw-r--r-- 2 yamada yamada 0 Jul 16 02:28 fileA.txt
-rw-r--r-- 2 yamada yamada 0 Jul 16 02:28 fileB.txt
-s, --symbolic-link
コピーする代わりにシンボリックリンクを作成します。
$ touch fileA.txt
$ cp -s fileA.txt fileB.txt
$ ls -l *
-rw-r--r-- 1 yamada yamada 0 Jul 15 01:27 fileA.txt
lrwxrwxrwx 1 yamada yamada 9 Jul 15 01:27 fileB.txt -> fileA.txt
-d
ハードリンクやシンボリックリンクをそのままコピーします。--no-dereference --preserve=links と同等です。
$ mkdir src                    # コピー元ディレクトリを作成
$ cd src
$ touch file.txt               # 通常ファイルを作成
$ ln file.txt hlink.txt        # ハードリンクファイルを作成
$ ln -s file.txt slink.txt     # シンボリックリンクファイルを作成
$ cd ..
$ cp -r src dst-without-d      # -d オプション無しでコピー
$ ls -l dst-without-d          # シンボリックリンクは保たれるが、ハードリンクが切れる
total 0
-rw-r--r-- 1 yamada yamada 0 Jul 16 02:37 file.txt
-rw-r--r-- 1 yamada yamada 0 Jul 16 02:37 hlink.txt
lrwxrwxrwx 1 yamada yamada 8 Jul 16 02:37 slink.txt -> file.txt
$ cp -rd src dst-with-d        # -d オプション付きでコピー
$ ls -l dst-with-d             # ハードリンクもシンボリックリンクも保たれる
total 0
-rw-r--r-- 2 yamada yamada 0 Jul 16 02:37 file.txt
-rw-r--r-- 2 yamada yamada 0 Jul 16 02:37 hlink.txt
lrwxrwxrwx 1 yamada yamada 8 Jul 16 02:37 slink.txt -> file.txt
-H
コピー元のファイルがディレクトリに対するシンボリックリンクの場合、シンボリックリンク先のディレクトリの内容をコピーします。コマンドラインで指定したファイルのみが対象です。
-L, --dereference
コピー元のファイルがディレクトリに対するシンボリックリンクの場合、シンボリックリンク先のディレクトリの内容をコピーします。コマンドラインで指定したファイルのみではなく、すべてのファイルが対象です。
-P, --no-dereference
SOURCE がシンボリックリンクでリンク先がファイルの場合、コピーするとシンボリックリンク先のファイルの中身をコピーしますが、-P を指定するとシンボリックリンクファイルをコピーします。下記の例では -P をつけずにコピーした fileC は通常ファイルとしてコピーされていますが、-P 付きでコピーした fileD はシンボリックリンクとしてコピーされています。シンボリックリンク先がディレクトリの場合は -P の有無に関わらずシンボリックリンクとしてコピーされます。
$ touch fileA              # fileAを作成
$ ln -s fileA fileB        # シンボリックリンクfileBを作成
$ cp fileB fileC           # -P オプション無しでfileCにコピー
$ cp -P fileB fileD        # -P オプション付きでfileDにコピー
$ ls -l
total 0
-rw-r--r-- 1 yamada yamada 0 Jul 14 22:30 fileA
lrwxrwxrwx 1 yamada yamada 5 Jul 14 22:30 fileB -> fileA
-rw-r--r-- 1 yamada yamada 0 Jul 14 22:31 fileC
lrwxrwxrwx 1 yamada yamada 5 Jul 14 22:31 fileD -> fileA
--keep-directory-symlink
コピー元とコピー先で、実ディレクトリなのか、ディレクトリに対するシンボリックリンクなのかの差異によってコピーが失敗するのを回避するために GNU cp 9.5 で追加されたオプションの様ですが、Linux ではその効果を確認することができませんでした。Linux での使用例をご存じの方が居れば教えてください。(参考)

属性維持

-a, --archive
アーカイブに適したオプションでコピーします。-dR --preserve=all オプションと同等です。シンボリックリンク、ハードリンク、モード、所有者、タイムスタンプなどの属性情報もすべてコピーします。
$ cp -ra ./src ./backup/20250720_src
-p
モード(パーミッション)、所有者、グループ、タイムスタンプ情報を維持します。--preserve=mode,timestamps,ownership と同等です。
--preserve[=ATTR_LIST]
モード(パーミッション)、所有者、タイムスタンプなども保持したままコピーします。ATTR_LIST には下記を指定します。カンマ(,)区切りで複数指定することも可能です。
  • mode : モード(パーミッション)
  • timestamps : タイムスタンプ(更新日時)
  • ownership : 所有者・グループ
  • links : ハードリンクの関係
  • context : SELinuxコンテキスト
  • xattr : 拡張属性(ファイルシステムがサポートしている場合)
  • all : すべて
--no-preserve=ATTR_LIST
ATTR_LIST で指定した属性をコピー時に保持しません。
--attributes-only
コピー先のファイルを新規に作成する際、ファイルの中身はコピーせず空のままとし、モード、所有者、タイムスタンプなどの属性情報のみをコピーします。下記の例では fileBfileA と同じ属性で作成されますが、中身は空になります。自作したバックアップスクリプトの評価の際に中身はコピーせず、コピー時間を短縮する際などに利用されます。
$ echo "AAA" > fileA                   # fileAを作成
$ chmod 400 fileA                      # モードを400に変更
$ cp --attributes-only fileA fileB     # --attributes-onlyオプションを指定してコピー
$ ls -l
total 4
-r-------- 1 yamada yamada 4 Jul 14 22:44 fileA
-r-------- 1 yamada yamada 0 Jul 14 22:44 fileB

上書きコピー

--remove-destination
コピー先に既存ファイルが存在する場合、一度そのファイルを削除してからコピーします。
--update[=UPDATE]
コピー先に同名ファイルがすでに存在する場合の動作を指定します。UPDATE には下記のいずれかを指定します。
  • all : 常に上書きします
  • none : 常に上書きしません。警告なしにスキップします
  • older : コピー先が古い時だけ上書きします(デフォルト)
-u
--update=older と同等です。
-f, --force
コピー先のファイルを開けない場合、そのファイルを一度削除してからコピーします。-n オプション指定時は無視されます。
-n, --no-clobber
コピー先のファイルが存在する場合、コピーをスキップします。警告メッセージも表示しません。GNU cp 9.5 からは非推奨とされています。--update も参照してください。

特殊機能

--reflink[=WHEN]
ファイルシステムがサポートする場合、CoW(Copy-on-Write)モードでコピーします。CoW ではディスク上のデータブロックは実コピーせず、参照だけであれば元ファイルのデータブロックを参照します。どちらかのファイルに書き込みが発生した時点でデータブロックのコピーと書き込みを行います。XFS や ZFS などで利用できます。WHEN には下記のいずれかを指定します。
  • auto : 可能であれば CoW コピーを行います。できない場合は通常コピーとなります。
  • always : 強制的に CoW コピーを行います。できない場合はエラーとなります。
  • never : CoW コピーを行いません。
--sparse=WHEN
スパースファイルに対する扱いを制御します。sparse は「まばら」という意味を持ちます。スパースファイルは、最初の 1MB は seek で読み飛ばされてデータの書き込みが無いなどの歯抜け領域が存在するファイルを効率的に扱う仕組みです。歯抜け部分には実際にはディスクのデータブロックを割り当てないことで、ディスクの省力化を行います。ext4 などのファイルシステムでサポートされています。WHEN には下記のいずれかを指定します。--sparse を指定しない時でも --sparse=auto の動作となるようです。
  • auto : コピー元がスパースファイルであればスパースファイルとしてコピーする
  • never : コピー元がスパースファイルでも常に全コピーする(データブロックを消費する)
  • always : コピー元がスパースファイルでなくてもゼロバイト領域があればスパースファイルとしてコピーする
$ dd if=/dev/zero of=fileA bs=1M count=10               # 10Mの通常ファイルを作成
$ dd if=/dev/zero of=fileB bs=1M seek=10 count=0        # 10Mのスパースファイルを作成

$ ls -lsh file*
10M -rw-r--r-- 1 yamada yamada 10M Jul 14 23:52 fileA   # ファイルサイズは両方とも10Mだが
  0 -rw-r--r-- 1 yamada yamada 10M Jul 14 23:52 fileB   # スパースファイルはブロックを使用していない(先頭の0)
                                                        # 各オプションでコピーしてみる
$ cp fileA fileA-normal
$ cp --sparse=auto fileA fileA-auto
$ cp --sparse=never fileA fileA-never
$ cp --sparse=always fileA fileA-always
$ cp fileB fileB-normal
$ cp --sparse=auto fileB fileB-auto
$ cp --sparse=never fileB fileB-never
$ cp --sparse=always fileB fileB-always

$ ls -lsh file*-*
  0 -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileA-always  # 通常ファイルでもalwaysであればスパース
10M -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileA-auto
10M -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileA-never
10M -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileA-normal
  0 -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileB-always  # alwaysの時はスパース
  0 -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileB-auto    # autoの時もスパース
10M -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileB-never   # neverはスパースでなくなる
  0 -rw-r--r-- 1 yamada yamada 10M Jul 15 00:03 fileB-normal  # オプションを指定しない場合もスパース
--copy-contents
デバイスファイルなどの特殊ファイルの中身も極力コピーしようと試みます。

セキュリティ

-Z
コピー先ファイルの SELinux のセキュリティコンテキストをデフォルトのタイプに設定します。
--context[=CTX]
コピー先ファイルの SELinux のセキュリティコンテキストを指定したタイプに設定します。

情報表示

-v, --verbose
実行状況を表示します。
--debug
デバッグ情報を出力します。-v オプションも付加されます。
--help
ヘルプメッセージを表示して終了します。
--version
バージョン情報を表示して終了します。

その他

-t, --target-directory=DIRECTORY
コピー先のディレクトリ名を引数ではなくオプションで指定します。xargsfind -exec {} + と組み合わせる際に便利です。
$ touch fileA.txt fileB.txt fileC.txt
$ mkdir backup
$ find . -name "*.txt" | xargs cp --target-directory=backup
または
$ find . -name "*.txt" -exec cp --target-directory=backup {} +
-x, --one-file-system
コピー先が別のファイルシステムにマウントされている場合にコピーをスキップします。
--strip-trailing-slashes
コマンドラインの SOURCE/ がある場合と無い場合で挙動が異なるため、コピー元に指定したディレクトリ名から / を取り除いて動作を統一的にするという説明ですが、Linux ではこのオプションの効能を確認することができませんでした。シンボリックリンクファイルをコピーする際には確かに / の有無により動作が変わるのですが、--strip-trailing-slashes をつけても動作は変わりませんでした。誰か効能をご存じの方がいれば...。