ファイルをコピーする copy

Windowsコマンドではcopyコマンドを使ってファイルをコピーすることができる。この際、Linuxユーザは注意が必要だ。

WindowsのcopyコマンドはLinuxのcpコマンドとは結構動きが異なる。似たようなものだと思うかもしれないが、ワイルドカードや+を使った指定などはLinuxユーザは混乱すると思う。今回はそのあたりを説明しよう。

Windowsのcopyコマンドの基本的な使い方は次のとおりだ。

copyコマンドの基本的な使い方

copy [/d] [/v] [/n] [/y | /-y] [/z] [/a | /b] <Source> [/a | /b] [+<Source> [/a | /b] [+ ...]] [<Destination> [/a | /b]]

パラメータの主な意味は次のとおり。

パラメータ 説明
/d 暗号化ファイルのコピーを許可するとともに、コピー先には復号化したデータを保存する
/v 新しいファイルが適切に書き込まれたかどうかを検証する。大切なデータをコピーする場合などに確認用として利用できる。各セクションをチェックするため、copyコマンドの実行速度は遅くなる
/n 8文字以上のファイル名または3文字以上の拡張子を持ったファイルをコピーする場合、可能であれば、ショートファイル名を使うようにする
/y ファイルを上書きする場合に確認プロンプトを表示しない
/~y ファイルを上書きする場合に確認プロンプトを表示する
/z ネットワークファイルをコピーする場合、コピーの途中で処理が止まってしまった場合、ネットワーク接続が再確立されてから再びコピーが行われる
/a ASCIIテキストファイルであることを指定
/b バイナリファイルであることを指定。コピー先がCOM1やLPT1といったデバイスの場合などには指定をすることになる。対象がCOM1やLPT1といった場合に/aを指定すると、特殊文字によって何らかの処理が発生してしまう可能性がある

Windowsのcopyコマンドでは/aでコピー元ファイルがASCIIテキストファイルであること、/bでコピー元ファイルがバイナリファイルであることを指定する。copyコマンドはファイルをただコピーするだけじゃないのかと思うかもしれないが、WindowsのcopyコマンドはLinuxのcpコマンドのようにデータをコピーするだけのコマンドではない。ASCIIテキストファイルではCtrl-Zをファイルの終端として理解するなど、挙動が異なっている。

さらにコピー元ファイルとコピー先ファイルの指定方法が独特だ。+や*を使った指定ができるのだが、Linuxのシェルが解釈するグロブとは異なり、特別な意味として解釈される。まず簡単にファイルの指定についてその動作を次にまとめておく。

ファイル指定 説明
コピー先指定なし コピー先を指定しない場合、カレントディレクトリにファイルをコピーする。ファイルは同じ名前で、コピー時の日付と時刻が書き込まれることになる。指定したファイルがカレントディレクトリに存在する場合にはコピーは行われない
サイズが0のファイル サイズが0のファイルはコピーされない。コピーしたい場合にはxcopyコマンドを使う必要がある
ディレクトリごとコピー copyコマンドはディレクトリを再帰的にコピーすることはできない。ディレクトリを再帰的にコピーする場合にはxcopyコマンドを使う必要がある
ファイルを結合 コピー元として複数のファイルを指定し、コピー先に1つのファイルを指定する場合、コピー元のファイルを結合してコピー先ファイルにコピーすることができる。この場合、ファイルはASCIIファイルであると仮定して処理が行われる。バイナリファイルを結合する場合には/bを指定する
ファイルを追記 コピー元として複数のファイルを指定し、コピー先を指定しない場合、コピー元のファイルのひとつめのファイルにほかのファイルの内容を追記することができる

copyコマンドはコピー先のファイルやディレクトリを指定しなくても動作する。その場合コピー先がカレントディレクトリとして解釈される。コピー元のファイルがカレントディレクトリに存在する場合にはコピーは行われない。

また、copyコマンドはサイズが0のファイルはコピーしないし、ディレクトリを再帰的にコピーもしてくれない。これら動作をしたい場合にはcopyコマンドではなくxcopyコマンドを使う必要がある。

ファイルの指定に+や*を使うと動作がLinuxのcpとは大きく異なってくる。これについては次の動作例で説明しようと思う。

copyコマンドの実行例とその内容

次のようにcopyコマンドを実行すると、テキストファイルのコピーを行うことができる。

テキストファイルのコピー

copy コピー元テキストファイル1.txt コピー先テキストファイル2.txt /a

ファイルを別のディレクトリにコピーする場合には、次のように最後にディレクトリを指定する。

ファイルを別のディレクトリへコピー

copy コピー元ファイルパス C:\コピー先ディレクトリパス\

ここまではLinuxのcpコマンドもほとんど同じだ。違ってくるのは次からだ。

まず、次のようにワイルドカードを使うと、*.txtに一致するすべてのファイルのデータが「結合先ファイル」に書き込まれる。Linuxであれば「cat *.txt > 結合先ファイル」と書くところだ。

ワイルドカードで指定したファイルを結合してファイルに書き込み

copy *.txt 結合先ファイル

似たような処理は次のように書くこともできる。次の場合だと+で結合したデータが「結合先ファイル」に書き込まれることになる。ワイルドカードを使った場合との違いは結合の順序を指定できることだ。

結合の順序を指定して結合してファイルに書き込み

copy 結合元ファイル1 + 結合元ファイル2  結合先ファイル

次のようにすべてのファイルを+で結合すると、今度は一番最初に指定したファイルでそれ以降のファイルの中身が追記で書き込まれることになる。Linuxであれば「cat 追記元ファイル1 追記元ファイル2 >> 追記先ファイル」と書くところだろう。

最初のファイルにデータが追記される

copy 追記先ファイル + 追記元ファイル1 + 追記元ファイル2

+と*を組み合わせて次のように書いた場合はさらに注意が必要だ。

対応するファイルごとに結合を行って新しいファイルに書き込む

copy *.txt + *.html *.doc

このように書くと、対応するファイル通しで処理が行われる。つまり、ファイル1.txt、ファイル1.htmlというファイルがあった場合、ファイル1.txtとファイル1.htmlの内容がファイル1.docというファイルに書き込まれる。このあたりはLinuxのコマンドとしては考えにくい指定方法だ。ファイル2.txtとファイル2.htmlが存在していれば、ファイル2.docに書き込まれる。Linuxで同じことをしようとすれば制御構文を使って処理を行うだろう。

なお、copyコマンドは次のように実行することでファイルの時刻を現在時刻に変更することができる。Linuxであればtouchコマンドを実行するようなものだ。

copyコマンドで現在時刻を反映させる方法

copy /b ファイルパス +,,

こんな感じでWindowsのcopyコマンドはLinuxのcpコマンドとはだいぶ動きが異なっている。Linuxのcpコマンドを使っている感覚で利用すると大切なファイルに対しておかしなデータ追加や結合を行ってしまいかねないので注意しておきたい。

参考資料