【Linux】cp-ファイル/ディレクトリのコピー|初学者に向けた備忘録

Linux
スポンサーリンク
はづき
はづき

こんにちは!はづきです

文系から一部上場IT企業に就職し、エンジニアをやっています

この記事はLinuxのcpコマンドについての備忘録です

cpはファイル/ディレクトリをコピーするためのコマンドです

一度作成したファイルを複製できるため、バックアップの作成に役立ちます

基本操作と頻繁に使用するオプションの実行例を紹介します。ぜひご参考ください

※この記事は初心者向けに平易に解説しています。正確な理解をしたい人は専門書・専門家をあたっていただければと思います。また、この記事の情報におけるCPの動作結果については自己責任でお願いします。

※本サイトにはプロモーション・広告が含まれています(はづきのブログより)

スポンサーリンク

cpコマンドでファイルをコピーする

cp {オプション} {コピー元※複数可} {コピー先}

cpコマンドは「cp {オプション} {コピー元※複数可} {コピー先}」で実行することが可能です

その実行例を以下で紹介していきます

指定したファイル名でコピーする

まずは、基本のcpコマンドの使い方を説明します

cpコマンドの引数として、「コピー元のファイル名」と「コピー先のファイル名」を指定します

今回は動作検証として、file1という名前のファイルを作成します。そして、file1をfile2という名前でコピーしてみます

cpコマンドの注意点として、既にコピー先のファイルが存在する場合は上書きされてしまいます。上書きをしたくない場合は「-n」オプション、上書きが起こる場合に確認メッセージを表示して欲しい場合は「-i」オプションを付けましょう ※この記事の後半で解説しています

#touchコマンドで「file1」というファイルを作成します
#lsコマンドで作成できたことを確認します
hazukiblog@hazukiBlog:~/work$ touch file1
hazukiblog@hazukiBlog:~/work$ ls
file1

#cpコマンドでfile1をfile2という名前でコピーします
#lsコマンドでfile2がコピーされたことを確認します
hazukiblog@hazukiBlog:~/work$ cp file1 file2
hazukiblog@hazukiBlog:~/work$ ls
file1  file2 

指定したディレクトリにコピーする

cpコマンドでは、コピー元ファイルとコピー先ファイルが別階層のディレクトリに存在しても実行できます

その場合は、相対パスや絶対パスを用いてファイル名を指定する必要があります

以下では、カレントディレクトリ配下にあるfile1という名前のファイルを、dir1という名前のディレクトリ配下にコピーします

コピー先としてディレクトリ名を指定すると、コピー元のファイルと同じ名前でコピーされます

#①dir1というディレクトリとfile1というファイルを作成しておきました
#②dir1配下に何もないことをlsコマンドで確認します
hazukiblog@hazukiBlog:~/work$ ls #①
dir1  file1
hazukiblog@hazukiBlog:~/work$ ls dir1 #②

#cpコマンドでfile1をdir1配下にコピーします
hazukiblog@hazukiBlog:~/work$ cp file1 /home/hazukiblog/work/dir1
#dir1配下にfile1がコピーされました
hazukiblog@hazukiBlog:~/work$ ls dir1
file1

#cpコマンドでfile1をfile2という名前でdir1配下にコピーします
hazukiblog@hazukiBlog:~/work$ cp file1 /home/hazukiblog/work/dir1/file2
#dir1配下にfile2という名前のファイルが作成されました
hazukiblog@hazukiBlog:~/work$ ls dir1
file1  file2

複数のファイルを同時にコピーする

cpコマンドでは複数のファイルを同時にコピーすることも可能です

コピー元のファイルを複数指定することで、コピー先として指定したディレクトリ配下にコピーされます

#動作検証のために、ファイルを3個とディレクトリを1個用意しました
hazukiblog@hazukiBlog:~/work$ touch file1 file2 file3
hazukiblog@hazukiBlog:~/work$ mkdir dir1
hazukiblog@hazukiBlog:~/work$ ls
dir1  file1  file2  file3

#cpコマンドで3個のファイルをdir1配下にコピーします
hazukiblog@hazukiBlog:~/work$ cp file1 file2 file3 dir1
#dir1配下に3個のファイルがコピーされました
hazukiblog@hazukiBlog:~/work$ ls dir1
file1  file2  file3

cpコマンドでディレクトリをコピーする

cpコマンドでは「-r」オプションを付けることでディレクトリをコピーすることもできます

通常、ファイルをコピーするのと同じようにディレクトリを指定すると以下のようなエラーが起こります

以下は、通常操作でdir1というディレクトリをdir2という名前でコピーしようとしたときの実行例です

#dir1をdir2という名前でコピーしようとすると以下のようにエラーになります
hazukiblog@hazukiBlog:~/work$ ls
dir1
hazukiblog@hazukiBlog:~/work$ cp dir1 dir2
cp: -r not specified; omitting directory 'dir1'

コピー先のディレクトリが存在しない場合

cpコマンドに「-r」オプションを付けてディレクトリをコピーしてみましょう

まずは、コピー先として指定するディレクトリが存在しない状態での実行例を紹介します

動作検証用にfile1、file2、file3という名前のついた3個のファイルを配下に持つdir1という名前のディレクトリを用意しました

このdir1をdir2という名前でコピーします。コピー実行後にdir2はdir1と同じように3個のファイルを配下に持っています

#動作検証のためにdir1を作成しました
#dir1配下には3個のファイルを用意しました
hazukiblog@hazukiBlog:~/work$ ls
dir1
hazukiblog@hazukiBlog:~/work$ ls dir1
file1  file2  file3

#-rオプションを付けてcpコマンドを実行します
hazukiblog@hazukiBlog:~/work$ cp -r dir1 dir2
#dir2という名前でdir1がコピーされました
hazukiblog@hazukiBlog:~/work$ ls
dir1  dir2
#dir2配下には3個のファイルがあります ※dir1をコピーしたため
hazukiblog@hazukiBlog:~/work$ ls dir2
file1  file2  file3

コピー先のディレクトリが存在する場合

次に、指定するコピー先のディレクトリが既に存在する場合の動作を確認します

動作検証用に3個のファイルを配下に持つdir1と配下に何も持たないdir2という名前のディレクトリを用意しました

この状態で、コピー元にdir1、コピー先にdir2を指定して実行すると、dir2配下にdir1がコピーされます

#動作検証のため、2個のディレクトリを用意しました
#dir1配下には3個のファイルがあり、dir2は空のディレクトリです
hazukiblog@hazukiBlog:~/work$ ls
dir1  dir2
hazukiblog@hazukiBlog:~/work$ ls dir1
file1  file2  file3
hazukiblog@hazukiBlog:~/work$ ls dir2

#-rオプションを付けてcpコマンドを実行します
hazukiblog@hazukiBlog:~/work$ cp -r dir1 dir2
#dir2が既に存在していたため、dir2配下にdir1がコピーされました
hazukiblog@hazukiBlog:~/work$ ls dir2
dir1
hazukiblog@hazukiBlog:~/work$ ls dir2/dir1
file1  file2  file3

cpコマンドのオプションを紹介

cpコマンドにはいくつかのオプションが用意されています

ここではその中から抜粋したオプションの使い方を紹介します

-i:上書き保存を実行するか確認する

-iは、コピー時に上書き保存が発生する場合に確認のメッセージを表示するオプションです

確認のメッセージに対して、y(Yes)を入力してEnterを押すと上書き保存が実行されます。反対に、n(No)を入力すると実行されずに終わります

※cpコマンドはコピー先に指定したファイルが既に存在する場合、上書き保存が発生します

hazukiblog@hazukiBlog:~/work$ ls
file1  file2
#既にfile2が存在している状態で-iオプションを付けてcpを実行する
hazukiblog@hazukiBlog:~/work$ cp -i file1 file2
cp: overwrite 'file2'? y #←このような確認メッセージが出る
hazukiblog@hazukiBlog:~/work$

-f:強制的にコピーを実行する

-fは、コピー先に指定したファイルが既に存在する場合に強制的に上書き保存でコピーを実行するオプションです

Linuxの動作環境・ディストリビューションによっては既存のファイルに上書きが発生する場合に確認が入ることがあります(-iオプション付与時のような動作に勝手になる)。-fではこれを無視することができます

hazukiblog@hazukiBlog:~/work$ ls
file1  file2
#既にfile2が存在している状態で-fオプションを付けてcpを実行する
#確認メッセージが出ずに上書き保存でコピーが実行される
hazukiblog@hazukiBlog:~/work$ cp -f file1 file2
hazukiblog@hazukiBlog:~/work$

-r:ディレクトリごとコピーする

-rは、ディレクトリごとコピーを行うためのコマンドです

既にこの記事の序盤で解説済みなので、ここでの解説は割愛します。詳しくはこの記事上部の「cpコマンドでディレクトリをコピーする」をご確認ください

-b:上書き時にバックアップファイルを作成する

-bは、コピー先に指定したファイルが既に存在する場合、コピー時にそのバックアップファイルを作成するためのオプションです

以下の実行例では、file2はfile1のコピーとして上書きされますが、file2のバックアップとしてfile2~が作成されます

このバックアップファイルの名前については、この後紹介する-Sオプションで指定することが可能です

hazukiblog@hazukiBlog:~/work$ ls
file1  file2
hazukiblog@hazukiBlog:~/work$ cp -b file1 file2
hazukiblog@hazukiBlog:~/work$ ls
file1  file2  file2~

-S(--suffix):バックアップファイルの名前に指定した接尾辞を付ける

-Sは、バックアップファイルに接尾辞を付けることのできるオプションです

以下は、バックアップファイル名に現在日時の情報を指定している実行例です

2通りのオプションの使用例を紹介します

#①「--suffix={バックアップファイルの接尾辞}」で指定する場合
#「%Y%m%d」で年月日を表しています
#「file2_20231102」という名前のバックアップファイルができました
hazukiblog@hazukiBlog:~/work$ ls
file1  file2
hazukiblog@hazukiBlog:~/work$ cp -b --suffix=_$(date +%Y%m%d) file1 file2
hazukiblog@hazukiBlog:~/work$ ls
file1  file2  file2_20231102

#②「-S {バックアップファイルの接尾辞}」で指定する場合
#「%Y%m」で年月を表しています
#「file2_202311」という名前のバックアップファイルができました
hazukiblog@hazukiBlog:~/work$ cp -b -S _$(date +%Y%m) file1 file2
hazukiblog@hazukiBlog:~/work$ ls
file1  file2  file2_202311  file2_20231102

-v:コピーしたファイルの情報を表示する

-vは、コピーしたファイルの情報を表示するオプションです

何がコピーされたのか明示的に表示されます

hazukiblog@hazukiBlog:~/work$ ls
dir1  file1  file2  file3
#以下の3行のようにコピー元とコピー先のファイルが表されます
hazukiblog@hazukiBlog:~/work$ cp -v file1 file2 file3 dir1
'file1' -> 'dir1/file1'
'file2' -> 'dir1/file2'
'file3' -> 'dir1/file3'
hazukiblog@hazukiBlog:~/work$

--parents:指定したディレクトリ階層に従ってコピーする

--parentsは、指定したディレクトリ階層をそのままコピー先のディレクトリ配下にコピーするオプションです

動作検証のため、以下のようなディレクトリとファイルを用意しました。dir2配下にdir1/file1をコピーします

|--dir1
|   |--file1
|
|--dir2
    |--dir1 ←コピーよって作成
        |--file1 ←コピーよって作成

--parentsを付与せずに「cp dir1/file1 dir2」とした場合は、dir2配下にfile1のみがコピーされてdir1はコピーされません。--parentsを付けることで、dir1ごとコピーされたことが以下の実行例でわかると思います

hazukiblog@hazukiBlog:~/work$ ls
dir1  dir2
hazukiblog@hazukiBlog:~/work$ cp --parents dir1/file1 dir2
hazukiblog@hazukiBlog:~/work$ ls dir2
dir1
hazukiblog@hazukiBlog:~/work$ ls dir2/dir1
file1
hazukiblog@hazukiBlog:~/work$

-n:コピー先のファイルが既に存在する場合、コピーしない

-nは、コピー先に指定したファイルが既に存在する場合、コピーを実行しないためのオプションです

cpコマンドによる上書き保存を防ぐことができます

hazukiblog@hazukiBlog:~/work$ ls
file1  file2
hazukiblog@hazukiBlog:~/work$ cat file1
file1です
hazukiblog@hazukiBlog:~/work$ cat file2
file2です
#-nを付けたことでfile2の中身が変わっていないことがわかります
hazukiblog@hazukiBlog:~/work$ cp -n file1 file2
hazukiblog@hazukiBlog:~/work$ cat file2
file2です

-u:コピー元ファイルがコピー先ファイルより新しい場合のみコピーする

-uは、コピー元ファイルがコピー先ファイルよりタイムスタンプ(mtime)の日時情報が新しい場合にのみコピーが実行されるオプションです

・タイムスタンプについての解説記事はこちら

以下で、タイムスタンプ情報の異なるfile1とfile2を用意して動作検証を行った実行例を紹介します

#cpコマンド実行前のfile1とfile2のに中身を確認
hazukiblog@hazukiBlog:~/work$ cat file1
file1です!
hazukiblog@hazukiBlog:~/work$ cat file2

#以下のstatコマンドよりタイムスタンプを確認
#file1のほうがfile2よりmtimeが新しいことがわかる
hazukiblog@hazukiBlog:~/work$ stat file1
  File: file1
  Size: 13              Blocks: 8          IO Block: 4096   regular file
Device: 820h/2080d      Inode: 2553        Links: 1
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/hazukiblog)   Gid: ( 1000/hazukiblog)
Access: 2023-11-05 15:55:51.091275037 +0900
Modify: 2023-11-05 15:55:48.641275829 +0900 #file1のmtime
Change: 2023-11-05 15:55:48.641275829 +0900 #file1のctime
 Birth: 2023-11-02 09:42:30.912872993 +0900

hazukiblog@hazukiBlog:~/work$ stat file2
  File: file2
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 820h/2080d      Inode: 3033        Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/hazukiblog)   Gid: ( 1000/hazukiblog)
Access: 2023-11-05 15:52:03.861342376 +0900
Modify: 2023-11-05 15:51:35.771354501 +0900 #file2のmtime
Change: 2023-11-05 15:51:35.771354501 +0900 #file2のctime
 Birth: 2023-11-05 15:51:35.771354501 +0900

#-uオプションを付与してcpを実行する
hazukiblog@hazukiBlog:~/work$ cp -u file1 file2
#file2のほうが古いためコピーされた
hazukiblog@hazukiBlog:~/work$ cat file1
file1です!
hazukiblog@hazukiBlog:~/work$ cat file2
file1です!

atimeとctimeではなくmtimeが比較対象であることがわかるように、以下の条件で検証しました

  • file1はfile2よりatimeとctimeが新しい
  • file1はfile2よりmtimeが古い

この条件下での期待結果は「コピーされない」になります

hazukiblog@hazukiBlog:~/work$ stat file1
  File: file1
  Size: 12              Blocks: 8          IO Block: 4096   regular file
Device: 820h/2080d      Inode: 2553        Links: 1
Access: (0777/-rwxrwxrwx)  Uid: ( 1000/hazukiblog)   Gid: ( 1000/hazukiblog)
Access: 2023-11-05 15:52:00.771343987 +0900 #file1のatime
Modify: 2023-11-02 09:43:07.302862886 +0900 #file1のmtime
Change: 2023-11-05 15:54:08.561310263 +0900 #file1のctime
 Birth: 2023-11-02 09:42:30.912872993 +0900
hazukiblog@hazukiBlog:~/work$ stat file2
  File: file2
  Size: 0               Blocks: 0          IO Block: 4096   regular empty file
Device: 820h/2080d      Inode: 3033        Links: 1
Access: (0644/-rw-r--r--)  Uid: ( 1000/hazukiblog)   Gid: ( 1000/hazukiblog)
Access: 2023-11-05 15:51:35.861342376 +0900 #file2のatime
Modify: 2023-11-05 15:51:35.771354501 +0900 #file2のmtime
Change: 2023-11-05 15:51:35.771354501 +0900 #file2のctime
 Birth: 2023-11-05 15:51:35.771354501 +0900

#-uオプションを付与してcpコマンドを実行しました
#その結果、期待結果通りコピーされませんでした
hazukiblog@hazukiBlog:~/work$ cp -u file1 file2
hazukiblog@hazukiBlog:~/work$ cat file1
file1です
hazukiblog@hazukiBlog:~/work$ cat file2
hazukiblog@hazukiBlog:~/work$

-p:権限や日時情報などのメタデータをそのままコピーする

-pは、以下のような権限や日時情報などのメタデータをそのままコピーできるオプションです

メタデータについての解説記事はこちら(lsコマンドの-lオプションにて)

  • 所有者、所有グループ(※私の動作検証では変わらなかった)
  • パーミッション
  • タイムスタンプ

通常のcpコマンドの実行だと、タイムスタンプがコマンド実行時の時間で更新されてしまいます。コピー元のタイムスタンプでコピーしたいときに使いましょう

#cp実行前のメタデータを確認します
hazukiblog@hazukiBlog:~/work$ ls -l
total 0
-rwxrwxrwx 1 sampleUser sampleUser 0 Dec  1  2022 file1
-rw-rw-r-- 1 hazukiblog hazukiblog 0 Nov  5 18:04 file2
-rwxrwxrwx 1 hazukiblog hazukiblog 0 Nov  5 18:04 file3

#通常実行と-pオプションを付与した実行で結果を比較します
hazukiblog@hazukiBlog:~/work$ cp file1 file2
hazukiblog@hazukiBlog:~/work$ cp -p file1 file3

#通常実行した場合(file2の状態)
#→パーミッションはそのまま、コマンド実行時のタイムスタンプになっています
#-pを付与して実行した場合(file3の状態)
#→パーミッションとタイムスタンプがfile1と同じ状態になる
hazukiblog@hazukiBlog:~/work$ ls -l
total 0
-rwxrwxrwx 1 sampleUser sampleUser 0 Dec  1  2022 file1
-rw-rw-r-- 1 hazukiblog hazukiblog 0 Nov  5 18:04 file2
-rwxrwxrwx 1 hazukiblog hazukiblog 0 Dec  1  2022 file3
hazukiblog@hazukiBlog:~/work$
#※私の検証では所有者、所有グループはfile1の情報で更新されませんでした

-s:シンボリックリンクを作成する

-sは、コピー先として指定したファイルをシンボリックリンクとしてコピーするためのオプションです

シンボリックリンクについての解説記事はこちら

#workディレクトリ配下にあるfile1をシンボリックリンクとしてコピーします
hazukiblog@hazukiBlog:~$ ls -l
total 4
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work

#-sを付与してcpコマンドを実行する
hazukiblog@hazukiBlog:~$ cp -s work/file1 symbolicLinkFile1

#symbolicLinkFile1はwork/file1のシンボリックリンクであることが確認できた
hazukiblog@hazukiBlog:~$ ls -l
total 4
lrwxrwxrwx 1 hazukiblog hazukiblog   10 Nov  5 18:31 symbolicLinkFile1 -> work/file1
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work

#以下、シンボリックリンクとして機能していることを検証
#work/file1の中身を書き換えるとsymbolicLinkFile1にも反映されている
hazukiblog@hazukiBlog:~$ cat symbolicLinkFile1
hazukiblog@hazukiBlog:~$ echo file1です > work/file1
hazukiblog@hazukiBlog:~$ cat symbolicLinkFile1
file1です
hazukiblog@hazukiBlog:~$

-l:ハードリンクを作成する

-lは、コピー先として指定したファイルをハードリンクとしてコピーするためのオプションです

・ハードリンクについての解説記事はこちら

#workディレクトリ配下にあるfile1をハードリンクとしてコピーします
hazukiblog@hazukiBlog:~$ ls -l
total 4
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work

#-lを付与してcpコマンドを実行する
hazukiblog@hazukiBlog:~$ cp -l work/file1 hardLinkFile1

#hardLinkFile1がwork/file1のハードリンクで作成されました
hazukiblog@hazukiBlog:~$ ls -l
total 8
-rw-rw-r-- 2 hazukiblog hazukiblog   12 Nov  5 18:33 hardLinkFile1
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work

#以下、ハードリンクとして機能していることを検証
#work/file1の中身を書き換えるとhardLinkFile1にも反映されている
hazukiblog@hazukiBlog:~$ cat hardLinkFile1
hazukiblog@hazukiBlog:~$ echo file1です > work/file1
hazukiblog@hazukiBlog:~$ cat hardLinkFile1
file1です
hazukiblog@hazukiBlog:~$

-d:シンボリックリンクをコピーする

-dは、シンボリックリンクをコピーする際にリンク先ごとコピーするためのオプションです

以下の実行例では、work/file1をリンク先とするシンボリックリンクのsymbolicLinkFile1をコピーしています。-dを付けることでコピーによって生まれたcp_symbolicLinkFile1もwork/file1をリンク先とするシンボリックリンクになっています

#cpコマンド実行前の状態を確認します
#work/file1のシンボリックリンクであるsymbolicLinkFile1が存在します
hazukiblog@hazukiBlog:~$ ls -l
total 4
lrwxrwxrwx 1 hazukiblog hazukiblog   10 Nov  5 18:40 symbolicLinkFile1 -> work/file1
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work

#-dオプションを付けてsymbolicLinkFile1をcp_symbolicLinkFile1としてコピーしました
hazukiblog@hazukiBlog:~$ cp -d symbolicLinkFile1 cp_symbolicLinkFile1

#cp_symbolicLinkFile1はwork/file1のシンボリックリンクとしてコピーされています
hazukiblog@hazukiBlog:~$ ls -l
total 4
lrwxrwxrwx 1 hazukiblog hazukiblog   10 Nov  5 19:00 cp_symbolicLinkFile1 -> work/file1
lrwxrwxrwx 1 hazukiblog hazukiblog   10 Nov  5 18:40 symbolicLinkFile1 -> work/file1
drwxrwxrwx 2 hazukiblog hazukiblog 4096 Nov  5 18:23 work
hazukiblog@hazukiBlog:~$

 

今回はLinuxのcpコマンドについて紹介しました

みなさんのお役に立てば幸いです。最後まで読んでいただきありがとうございました

おしまい

コメント

タイトルとURLをコピーしました