【Windows】robocopyの終了コード一覧と意味|8以上が失敗。バッチ・PowerShellでの判定方法

スポンサーリンク
Windows
スポンサーリンク

私はrobocopyで、PCのDドライブをNASに、Windowsのバックアップを別のドライブにコピーしている。どちらのスクリプトも、robocopyの終了コードが8以上の時だけ「エラーがありました」と表示するようにしている。

robocopyは、ちゃんとコピーできた時でも0以外の終了コードを返す。普通のコマンドと同じつもりで「0以外ならエラー」と判定すると、成功しているのにエラー扱いになってしまう。

結論から書くと、robocopyの終了コードは8未満なら成功(コピーに失敗したファイルは無い)、8以上なら失敗がある。Microsoftのドキュメントにも「8以上の値は、コピー操作中に少なくとも1つの障害が発生したことを示します」と書かれている。

robocopyの終了コード一覧

robocopyの終了コードは、次の5つの値の足し算になっている。たとえば3は「1(コピーした)+2(コピー先に余分なファイルがある)」だ。

値 意味 判定
0 コピーするものが無かった。コピー元とコピー先がすでに同じ状態 成功
1 1つ以上のファイルをコピーした 成功
2 コピー先に、コピー元に無いファイルやフォルダ(Extras)がある 成功
4 不一致(Mismatch)のファイルやフォルダがある。同じ名前でコピー元はファイル、コピー先はフォルダ、など 成功(要確認)
8 コピーできなかったファイルやフォルダがある(再試行の回数を超えた) 失敗
16 重大なエラー。1つもコピーしていない。オプションの書き間違いや、コピー元・コピー先にアクセスできない時 失敗

Microsoftのrobocopy - Microsoft LearnとRobocopy ユーティリティで使用されるリターン コード - Microsoft Learnには、0〜8の組み合わせの説明と「8以上は失敗」が載っている。4と16の個別の意味は、Microsoftの技術者のブログ記事Robocopy exit codes - Microsoft Learn(アーカイブ)を参考にした。

組み合わせで出てくる値の意味は、次のとおり。

値 内訳 意味
3 1+2 コピーした。コピー先に余分なファイルもある
5 1+4 コピーした。不一致のファイルもある
6 2+4 余分なファイルと不一致のファイルがある。コピーはしていない
7 1+2+4 コピーした。余分なファイルと不一致のファイルもある
9〜15 8+α コピーできたファイルもあるが、失敗したファイルもある

/MIRや/PURGEを付けている時は、コピー先の余分なファイルは削除される。それでも、削除した分は2として数えられる(下の実験の7番)。

実際に終了コードを出してみた

本当にこの値が返るのか、私のPC(Windows 11 Pro)で、テスト用のフォルダを使って1つずつ試した。/R:0 /W:0(再試行しない)を付けて実行し、PowerShellの$LASTEXITCODEで終了コードを見た。

やったこと 終了コード
新しいファイルを2つコピー 1
もう一度実行(変化なし) 0
コピー先にだけファイルを置いて実行 2
新しいファイルを1つ追加+コピー先にだけファイルがある 3
コピー元のファイルと同じ名前のフォルダをコピー先に作って実行(不一致) 4
コピー先のファイルを別のプロセスで開いたまま、更新したファイルをコピー 8
/MIRで、コピー先にだけあるファイルを削除 2
存在しないフォルダをコピー元にした 16
存在しないオプション(/XYZ)を付けた 16

ファイルを開いたままにした時(終了コード8)の出力は次のとおり(パスは短くした)。集計のFAILED(日本語のログでは「失敗」)の列が1になっている。

	    Newer     		      13	a.txt
2026/11/08 19:41:21 ERROR 32 (0x00000020) Copying File D:\test\src\a.txt
The process cannot access the file because it is being used by another process.
------------------------------------------------------------------------------
               Total    Copied   Skipped  Mismatch    FAILED    Extras
    Dirs :         1         0         1         0         0         0
   Files :         4         0         3         0         1         0

コピー元が無い時はERROR 2 (0x00000002) Accessing Source Directory、オプションを書き間違えた時はERROR : Invalid Parameter #3 : "/XYZ"と出て、どちらも1つもコピーせずに16で終わった。NASやドライブが見えなくてコピー元・コピー先にアクセスできない時も16になるはずだが、それは試していない。

バッチファイルで8以上を判定する

バッチファイルではif errorlevel 8で判定する。Microsoftのif - Microsoft Learnにあるとおり、errorlevel 8は「終了コードが8以上」の時に真になる。8ちょうどではないので、9や16もここに入る。

@echo off
robocopy "D:\data" "E:\backup\data" /MIR /R:3 /W:3 /log+:"E:\backup\robocopy.log" /np
if errorlevel 8 (
  echo コピーに失敗したファイルがあります。ログを確認してください。
  exit /b 1
)
echo 完了しました。
exit /b 0

同じことは%errorlevel%を使って次のようにも書ける。GEQは「以上」の比較だ。

if %errorlevel% GEQ 8 echo コピーに失敗したファイルがあります。

注意点が2つある。

  • if errorlevelは「その直前に実行したプログラム」の終了コードを見る。robocopyとifの間にechoなどを挟まず、robocopyの直後に判定する
  • ( )の中で%errorlevel%を使うと、ブロックに入る前の値に展開されてしまう。( )の中でrobocopyを実行して判定する時はif errorlevel 8の方を使う(robocopyでコピー先フォルダが非表示になる原因と直し方のバッチがこの形)

PowerShellで8以上を判定する

PowerShellでは、外部のプログラムの終了コードは$LASTEXITCODEに入る(about_Automatic_Variables - Microsoft Learn)。robocopyの直後に変数に取っておき、-ge 8で判定する。

robocopy "D:\data" "E:\backup\data" /MIR /R:3 /W:3 /log+:"E:\backup\robocopy.log" /np
$rc = $LASTEXITCODE
if ($rc -ge 8) {
    Write-Host "コピーに失敗したファイルがあります(終了コード $rc)。ログを確認してください。" -ForegroundColor Red
    exit 1
}
Write-Host "完了しました(終了コード $rc)。" -ForegroundColor Green
exit 0

$?は使わない方がよい。$?は外部のプログラムの終了コードが0以外だとFalseになるので、ファイルをコピーできた時(終了コード1)でも「失敗」と判定されてしまう。

私がNASへのバックアップに使っているスクリプトも、この形で判定している(RobocopyでローカルフォルダのデータをID/パスワード付きのNASにバックアップする)。

タスクスケジューラで「失敗」と表示させないために

タスクスケジューラやジョブ管理ツールでrobocopyを動かすと、終了コード1(コピーした)でも「前回の実行結果」が(0x1)になり、失敗したように見える。上のバッチ・PowerShellの例のように、最後にexit /b 0・exit 0(8未満の時)とexit /b 1・exit 1(8以上の時)を返すようにしておくと、本当に失敗した時だけ0以外になる。

8以上になったら、ログの「失敗」を見る

終了コードは「失敗があった」ことしか分からない。どのファイルで失敗したかは、/log+:で残したログを見る。ログの最後の集計の「失敗」(英語の表示ではFAILED)の列が0でなければ、ログの中に「エラー」(ERROR)と書かれた行があり、ファイル名と理由(アクセスが拒否された、別のプロセスが使用中、など)が書かれている。

失敗の原因として、私が実際に当たったものは次の2つ。

参考

コメント

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