2011年8月24日水曜日

COPYコマンドの /Aと/Bの意味 - Windowsのコマンドプロンプト(bat,cmd)

Windowsコマンド。ファイルとフォルダー関連
○Windows XP
COPYコマンドのヘルプには、次のような説明が出てきます。

o /A = ASCII テキスト ファイルとして扱います。
o /B = バイナリ ファイルとして扱います。

そこで、これらのオプションを指定した時に、何が起きるのかを調べてみました。


**** 結論
o 通常のファイルコピーでは、/A は使わない方が安全です。
o 複数のファイルを結合して1つのファイルにする時は、何も指定しないと /A でコピーします。
    + この時、「Unicode」形式で保存したテキストファイル以外は、/B を付ける等の対応が必要です。

**** 詳細
** 2つのファイル形式の違い
o バイナリ ファイル = ファイルの最後に、余分な文字コードを追加しない形式です。
o ASCII テキスト ファイル = 2種類の形式があります。
    + 文字コードが「Unicode」の時は、ファイルの先頭2文字が文字コード 0xFF 0xFE で始まる形式です。
        + 「Unicode」 = 「UTF-16 LE の、BOM付き」の事です。
        + この動作は、メモ帳で保存する時と同じです。
    + 文字コードが「Unicode」以外の時は、ファイルの最後に、文字コード 0x1A を追加する形式です。
        + もちろん、ファイル内容の途中で文字コード 0x1Aは出てきません。
        + (文字コード 0x1Aが出てきた時点で、ファイルの最後とみなします。)
        + この動作は、メモ帳で保存する時とは異なります。

o 確認した文字コードは
    + 「Unicode」 = 「UTF-16 LE BOM付き」 = 特殊扱い
    + 「Unicode big endian」 = 「UTF-16 BE BOM付き」
    + 「ANSI」 = WIndows版 Shift-JIS
    + 「UTF-8」 = UTF-8 BOM付き
    + UTF-8 BOM無し
    + UTF-16 LE BOM無し
    + EUC-JP
    + 上記以外の文字コードは未確認です。

** COPY コマンドの動作
o ファイルをコピーする時、COPY コマンドは次のように仮定します。
    + 1対1のコピーの時は、バイナリファイルであると仮定
    + 複数ファイルを連結して1つのファイルにコピーする時は、ASCIIテキストファイルであると仮定
    + /A や /B オプションを付ける事で、その仮定を打ち消す事が出来ます。
o オプションの判定方法について
    + 同じ場所で /B /A のように並べて書いた時は、後ろに書いたオプションが有効になります。
--------
rem 次の2つのコマンドは、同じ意味です。
copy ネギ.txt /b /a ミクさん.txt
copy ネギ.txt /a ミクさん.txt
--------

    + コピー元ファイルのオプションが指定されていない時
        + そのファイル名の左に書かれているオプションを参照します。
        + 複数のファイルを「+」で連結している時は、1つ左、無ければ2つ左、というの順で参照します。
--------
rem 次の2つのコマンドは、同じ意味です。
copy ネギ1.txt /b + ネギ2.txt ミクさん.txt
copy ネギ1.txt /b + ネギ2.txt /b ミクさん.txt
--------

    + コピー先ファイルのオプションが指定されていない時
        + COPYコマンドの直後の場所に書かれているオプションを参照します。
    + 参照先にも指定が無い時は、
        + 1対1でファイルコピーする時は、/B = バイナリファイル扱い
        + 複数ファイルを1ファイルにコピーする時は、/A = ASCII テキストファイル扱い

o コピー元ファイルが/A オプション(扱い)の時の動作
    + ファイルの先頭2文字が、文字コード(0xFF 0xFE)から始まる時
        + 文字コードが「Unicode」の場合です。
        + 複数ファイルを1つのコピーする時に、2つ目以降のファイルの先頭の文字コード(0xFF 0xFE)をスキップしてコピーします。
    ファイルの先頭2文字が、文字コード(0xFF 0xFE)以外で始まる時
        + ファイルの中に文字コード(0x1A)が登場すると、その文字(0x1A)の手前までをコピーします。
    + その他の時は、素直にファイルをコピーします。
o コピー元ファイルが/B オプション(扱い)の時の動作
    + 素直にファイルをコピーします。

o コピー先ファイルが/A オプション(扱い)の時の動作
    + 文字コードが「Unicode」以外の場合
        + ファイルをコピーした後に、コピー先ファイルの最後に文字コード(0x1A)を追加します。
o コピー先ファイルが/B オプション(扱い)の時の動作
    + ファイルをコピーした後に、文字コードを何も追加しません。


**** メモ
o Windowsのメモ帳の動作は、COPYコマンドの /A とは少し異なります。
    + 文字コード「Unicode」で保存する時の動作は、COPYコマンドの /A と同じです。
        + ファイルの先頭に、文字コード(0xFF 0xFE)を付けます。
    + その他の文字コードで保存する時の動作は、COPYコマンドの /A と異なります。
        + 文字コード「ANSI」 = WIndows版 Shift-JISで保存する時は、
            + ファイルの最後に、文字コード(0x1A)を付けません。
                + COPYコマンドの /B = バイナリファイルと同じ形式です。
            + また、ファイル中に文字コード(0x1A)が含まれていると、小さな矢印のように表示します。
        + 文字コード「Unicode big endian」で保存する時は、
            + ファイルの先頭に、文字コード(0xFE 0xFF)を付けます。
            + ファイルの最後に、文字コード(0x1A)を付けません。
        + 文字コード「UTF-8」で保存する時は、
            + ファイルの先頭に、文字コード(0xEF 0xBB 0xBF)を付けます。
            + ファイルの最後に、文字コード(0x1A)を付けません。
o ファイルを1対1でコピーする時は、オプション無しで問題はありません。
o 一方、複数のファイルを連結して1つのファイルにコピーする時には、問題が起こる場合があります。
    + COPYコマンドは、各ファイルをASCII テキストファイルだと仮定します。
    + ですので、ファイルの文字コードに応じて、/B オプションを使うなどの対応が必要になります。


**** 確認したバージョン
o Windows XP Service Pack 3(32bit) + Windows Update 2011年8月版


==
関連ページ:
    ▼Windowsコマンド。ファイルとフォルダー関連▼ABC順
    ▼Windowsコマンド一覧▼ABC順
    ▼コマンドプロンプト画面
    ▼制作メモ
    > DISKCOPY = フロッピーディスクの内容を別のフロッピーディスクにコピーする。途中に質問あり版
    MOVE = ファイルを移動する
    REN = ファイルやフォルダーの名前を変更する
(2011年8月25日変更。大幅加筆と、/Aの動作解釈誤りを訂正)