連載
» 2016年06月01日 05時00分 UPDATE

Linux基本コマンドTips(18):【 cp 】コマンド(応用編その1)――ディレクトリをコピーする

本連載は、Linuxのコマンドについて、基本書式からオプション、具体的な実行例までを紹介していきます。前回に続き、今回も「cp」コマンドを取り上げます。

[西村めぐみ,@IT]
「Linux基本コマンドTips」のインデックス

Linux基本コマンドTips一覧

 本連載では、Linuxの基本的なコマンドについて、基本的な書式からオプション、具体的な実行例までを分かりやすく紹介していきます。前回に続き、今回もファイルをコピーするための「cp」コマンドで、ディレクトリをコピーする方法を解説します。

cpコマンドとは?

 Linuxでは、ファイルをコピーする際には「cp」コマンドを使います。「cp コピー元 コピー先」のように指定します。コピー先にディレクトリを指定した場合は、指定したディレクトリにコピー元と同じ名前のファイルが作成されます。


cpコマンドの書式

cp [オプション] コピー元 コピー先

cp [オプション] ファイル1 ファイル2…… コピー先ディレクトリ

※[ ]は省略可能な引数を示しています



cpコマンドの主なオプション

 cpコマンドの主なオプションは次の通りです。

●一般的なオプション
短いオプション 長いオプション 意味
-i --interactive 上書きする前に確認する
-v --verbose 実行内容を表示する
-n --no-clobber 存在するファイルを上書きしない
-f --force 強制的に上書きする
-b --backup=方法 上書きされるファイルのバックアップを作る(「ln」コマンド参照
[方法]:「numbered」または「t」の場合は番号の添え字、「simple」または「never」の場合はファイル名の末尾に「~」または「-S」オプションか環境変数で指定した文字を付けるシンプルなバックアップ(「-b」と同じ)、「existing」または「nil」の場合は既にあるファイルに従う(ない場合はで「simple」と同じ)
-S 接尾辞 --suffix=接尾辞 バックアップファイルを作る際のファイル名末尾に付ける文字(無指定時は「~」1文字、または環境変数「SIMPLE_BACKUP_SUFFIX」に従う)

●リンク関係のオプション
短いオプション 長いオプション 意味
-d シンボリックリンク自体をコピーする(--no-dereference --preserve=linksと同様)
-s --symbolic-link コピーの代わりにシンボリックリンクを作成する
-l --link コピーの代わりにファイルのハードリンクを作成する
-L --dereference コピー元のシンボリックリンクを常にたどる
-P --no-dereference コピー元にあるシンボリックリンクをたどらない

●ディレクトリ関係のオプション
短いオプション 長いオプション 意味
-R,-r --recursive コピー元にディレクトリを指定した場合、再帰的に(サブディレクトリも含めて)コピーする
-t ディレクトリ名 --target-directory=ディレクトリ名 「-t」で指定したディレクトリにコピーする
-T --no-target-directory コピー先(最後の引数)がディレクトリでも特別扱いしない

●属性関係のオプション
短いオプション 長いオプション 意味
-a --archive サブディレクトリや属性なども含め、可能な限り全てを保持しながらコピーする(-dR --preserve=allと同様)
-u --update コピー元のファイルがコピー先ファイルより新しいか新規ファイルの場合だけコピーする
-p パーミッションと所有者とタイムスタンプを保持する(--preserve=mode,ownership,timestamps相当)
--preserve[=属性リスト] 指定した属性を保持する。属性を指定しなかった場合は、mode(パーミッション)、ownership(所有者)、timestamps(タイムスタンプ)が保持される。その他、context(コンテキスト情報)、links(ディレクトリ内のハードリンク)、xattr(ファイルシステムの拡張属性)、all(可能な限り全ての属性)を指定可能
--no-preserve=属性リスト 指定した属性を保持しない
--attributes-only ファイルのデータをコピーせず、ファイルの属性のみコピーする


「cp -RT」でディレクトリをコピーする

 cpコマンドでディレクトリの中身も含めて全てコピーしたい場合は、「cp -RT dir1 dir2」のように指定します。コマンドラインでファイル名を補完しながら入力すると、「cp -RT dir1/ dir2/」のようにディレクトリ名の末尾に「/」が付加されますが、動作は同じです。

コマンド実行例

cp -RT dir1/ dir2/

(「dir1」というディレクトリを中身も含めて全て「dir2」にコピーする)


 上記の実行例では「dir1」と「dir2」がディレクトリであることを明示するため、両方に「/」を付けていますが、「dir2」というディレクトリが存在しない場合は、ファイル名補完で入力すると「cp -RT dir1/ dir2」となるのが自然でしょう。動作は同じです。

cp -RT dir1 dir2
cp -RT dir1/ dir2
cp -RT dir1/ dir2/
ディレクトリ「dir1」を中身も含めて全て「dir2」というディレクトリへコピーする場合、上記3つのコマンドは全て同じ動作になる


「cp -R」と「cp -RT」の違いは?

 「-R」は、ファイルを“再帰的にコピーする”というオプションです。「-R」で指定したディレクトリの中にサブディレクトリが存在すればそれも、その中にまたディレクトリがあればそれも……という意味になります。従って、ディレクトリをコピーして同じ内容の新しいディレクトリを作成するならば、「-R」オプションだけでOKです。

 ここで、「dir2」というディレクトリが既に存在する場合、「cp -R dir1 dir2」と「cp -RT dir1 dir2」では結果が変わります。

 「-T」は、「--no-target-directory」というオプションです。cpは「(1)最後の引数をコピー先として扱う」「(2)最後の引数がディレクトリだった場合は、指定したファイルをそのディレクトリの中にコピーする」ということになっていますが、「-T」を指定した場合は(2)の処理を行いません。コピー元とコピー先がディレクトリであれば、単にディレクトリのコピーを行います。

 少々分かりにくいので実際の動作を見ながら説明していきましょう。

「コピー先として指定したディレクトリが存在しない」場合の動作

 まずは、「コピー先として指定したdir2が存在しない」というケースです。この場合、「cp -RT dir1 dir2」と「cp -R dir1 dir2」の実行結果は同じになります。なお、同じコマンドを試す場合は、以下のようにテスト用に新しいディレクトリを作成し、その中で実行した方が分かりやすく、かつ安全です。

$ mkdir testdir	(「testdir」というディレクトリを作成する)
$ cd testdir	(「testdir」に移動する)

 以降の実行例は、全てこの「testdir」ディレクトリの中で行っています。

$ mkdir dir1	(「dir1」というディレクトリを作成する)
$ touch dir1/file1	(「dir1」の中に「file1」というファイルを作成する)
$ find	(カレントディレクトリにあるファイルを全て表示)
.
./dir1
./dir1/file1
$ cp -R dir1 dir2	(「dir1」を「dir2」へコピー(「dir1」はディレクトリ、「dir2」は存在しない……コピー元がディレクトリなので新規ディレクトリが作成される))
$ find
.
./dir1
./dir1/file1
./dir2
./dir2/file1
「dir2」が作成され、「dir1」の中にあった「file1」がコピーされている

「コピー先として指定したディレクトリが存在する」場合の動作

 次に、「dir2」が既に存在するケースです。まずは「cp -R」で見てみましょう。以下の実行例では動作を明確にするため、いったん「dir1」と「dir2」を削除し、あらためて「dir1」と「dir2」を用意してからcpコマンドを実行しています。

$ rm -rf dir1 dir2	(「dir1」と「dir2」をいったん削除)
$ mkdir dir1	(「dir1」というディレクトリを作成する)
$ mkdir dir2	(「dir2」というディレクトリを作成する)
$ touch dir1/file1	(「dir1」の中に「file1」というファイルを作成する)
$ touch dir2/file2	(「dir2」の中に「file2」というファイルを作成する)
$ find
.
./dir1
./dir1/file1
./dir2
./dir2/file2	(dir1にはfile1が、dir2にはfile2がある)
$ cp -R dir1 dir2	(「dir1」を「dir2」にコピーする(コピー先がディレクトリなので、“「dir2」の中にコピーする”という意味になる))
$ find
.
./dir1
./dir1/file1
./dir2
./dir2/file2
./dir2/dir1
./dir2/dir1/file1
「dir2」の中に「dir1」が作成されている。「dir1」の中には「file1」もある

 動作が分かりにくい場合は、「ls」コマンドで確認してみましょう。「--color」や「-F」「-l」オプションを付けると、ディレクトリかどうかを見分けやすくなります。

ワンポイント

 「find」コマンドは「指定したファイルやディレクトリを指定した場所から探す」というコマンドですが、ファイルを指定しないと“全てを探す”、場所を指定しないと“カレントディレクトリを探す”という意味になり、結果としてカレントディレクト下のファイルとディレクトリが全て表示されることになります。

 「-ls」オプションを付けて「find -ls」とすると、「ls -l」のような表示(「ls -dils」の書式)となります。また、lsコマンドならば、「-R」オプションで再帰的な表示が可能です。「ls -RF」や「ls -Rl」が分かりやすいでしょう。ディレクトリのツリー構造を表示できる「tree」コマンドが使える環境であれば、そちらの方がより直感的に理解できるでしょう。


 次に「cp -RT」の実行例です。「dir1」と「dir2」を削除し、同じファイル構成にしてから試しています。

$ rm -rf dir1 dir2	(「dir1」と「dir2」をいったん削除)
$ mkdir dir1	(「dir1」というディレクトリを作成する)
$ mkdir dir2	(「dir2」というディレクトリを作成する)
$ touch dir1/file1	(「dir1」の中に「file1」というファイルを作成する)
$ touch dir2/file2	(「dir2」の中に「file2」というファイルを作成する)
$ find
.
./dir1
./dir1/file1
./dir2
./dir2/file2	(「dir1」には「file1」が、「dir2」には「file2」がある)
$ cp -RT dir1 dir2	(「dir1」を「dir2」にコピーする)
$ find
.
./dir1
./dir1/file1
./dir2
./dir2/file2
./dir2/file1
「dir1」が「dir2」にコピーされた結果、「dir1」にあった「file1」が「dir2」直下にコピーされている

 「-T」は比較的新しいオプションです。「-T」オプションが使用できない場合にコピー先のディレクトリが既に存在すると、「cp -R dir1/* dir2/」のように“dir1の中身をdirにへ”と明示するようにします。また、ディレクトリのコピーがバックアップ用途であれば、「rsync」コマンドなどの使用を検討するのもよいでしょう。

ワンポイント

 「dir2」というディレクトリがない場合は、「dir2/」のように「/」が補完されないので分かります。シェルスクリプトの場合、“事前に「dir2」というディレクトリの存在を確認し、存在していない場合は「mkdir dir2」で作成する”というような処理をします。

 なお、既に「dir2」がある場合に「mkdir dir2」を実行しても、「既に存在している」というエラーになるだけで新規で上書きされたり、余計なディレクトリが作成されたりすることはありません。毎回とにかく「mkdir dir2」を実行するという方法でも、操作結果としては問題ありません。


ワンポイント

 上記実行例では「rm -rf dir1 dir2」のように、まとめて引数を指定しています(「rm」はファイルを削除するコマンドで、「-rf」はディレクトリであっても中身も含めて全て削除するというオプション)。

 「mkdir」コマンドや「touch」コマンドも、「mkdir dir1 dir2」「touch dir1/file1 dir2/file2」のようにまとめて引数を指定できます。

 コマンドを試す場合には、代表的なオプションを1回ずつではなく、いろいろなパターンで試すことになると思います。その際、「rm -rf dir1 dir2;mkdir dir1 dir2;touch dir1/file1 dir2/file2」のように“セミコロン(;)”で区切りながら複数のコマンドを1行で実行しておくと、再度実行する際に「ヒストリ」機能で呼び出せるので便利です。




筆者紹介

西村 めぐみ(にしむら めぐみ)

PC-9801N/PC-386MからのDOSユーザー。1992年より生産管理のパッケージソフトウェアの開発およびサポート業務を担当。のち退社し、専業ライターとして活動を開始。著書に『図解でわかるLinux』『らぶらぶLinuxシリーズ』『はじめてでもわかるSQLとデータ設計』『シェルの基本テクニック』など。2011年より、地方自治体の在宅就業支援事業にてPC基礎およびMicrosoft Office関連の教材作成およびeラーニング指導を担当。


Copyright© 2017 ITmedia, Inc. All Rights Reserved.

@IT Special

- PR -

TechTargetジャパン

この記事に関連するホワイトペーパー

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。