robocopy差分・増分バックアックをする方法と注意

目次

概要

Windowsでrobocopyコマンドを利用して、バックアップをとることにしました。

その際に、差分バックアップや増分バックアップを実施しようとしたのですが、robocopyの仕様上、できないことがあると分かりました。

ここでは、私が実際にバックアップをとるためにやったことと、バックアップとしてあきらめたことについて書きました。

やりたいこと

Windowsで保存している作業ファイルなどについて、バックアップをとりたいと思いました。その際にできるのであれば、差分バックアップ、もしくは増分バックアップをとりたいと思いました。

Windowsでバックアップをとるには、バックアップ用のソフトウェアをインストールして利用するということもできますが、それらは基本的に有料であることが多いです。できるのであれば、無料でバックアップをとりたいところです。

そのほかにも、Windows標準のバックアップ方法として「ファイル履歴」やOneDriveを利用したバックアップ方法がありますが、それらは機能的に好きなファイルやフォルダをバックアップできなかったり、OneDriveの有料プランを契約しないと容量が全然足りなかったりするため、諦めました。

そこで、今回私がバックアップを取った方法は、Windowsに標準でインストールされている、robocopyコマンドを利用した方法です。

robocopyコマンドは、標準でインストールされていることから、バックアップ等でファイルやフォルダを別の場所にコピーすることができるコマンドです。今回の用途にはぴったりです。

方法

バックアップとして、ファイルやフォルダをコピーするだけであれば、robocopyコマンドを利用するだけですが、コピー場所を指定したり、コピーするファイルやフォルダを選択したりするのであれば、それ以外のコマンドも必要です。ここでは、それらを含めた、PowerShellのスクリプトを用意しました。

robocopyコマンドには、たくさんのオプションがあります。このオプションによって、コピー時の動作を変更することができます。今回は、差分や増分でバックアップを取らず、そのままコピーをすることにしました。また、ログを保存するようにもしています。

なぜ、差分や増分でバックアップを取らなかったのかというと、robocopyの仕様として、増分や差分でバックアップする際に、削除したファイルやフォルダを反映させることができないからです。つまり、コピー元の場所でファイルを削除した際などに、それがバックアップに反映されず、もしもバックアップから復元を行う際に、完璧に復元することができないということです。

ここに完成したスクリプトを示します。

# バックアップするフォルダの配列
$backupFolders = @(
    "C:\Users\<ユーザー名>\Documents",
    "C:\Users\<ユーザー名>\Downloads",
)

# バックアップ先のフォルダ
$backupPath = "D:\Windows Backup"

# バックアップ先のフォルダがあるか確認
# 存在しない場合は終了
if (!(Test-Path $backupPath)) {
    Write-Host "バックアップ先のフォルダが存在しません。"
    Write-Host "バックアップ先のフォルダを作成してください。"
    exit 1
}

# バックアップ先にLogフォルダがあるか確認
# 存在しない場合は作成する
if (!(Test-Path "$backupPath\log")) {
    Write-Host "バックアップ先にLogフォルダが存在しません。"
    Write-Host "Logフォルダを作成します。"
    New-Item -ItemType Directory -Path "$backupPath\log"
}

# 現在時刻を取得
$now = Get-Date -Format "yyyyMMdd_HHmmss"

# バックアップ先のフォルダにバックアップ
try {
    foreach ($path in $backupFolders) {
        # フォルダ名だけ取り出す
        $folder = Split-Path $path -Leaf

        Write-Host "バックアップを開始します。"
        Write-Host "バックアップ元のフォルダ: $path"
        Write-Host "バックアップ先のフォルダ: $backupPath\$folder"

        # 空白を含むフォルダ名の場合は""で囲む
        robocopy "$folder" "$backupPath\BackupFiles\$folder\" /MIR /PURGE /MT:8 /R:3 /W:3 /NP /NFL /NDL /NJH /NJS /NS /NC /COPY:DT /DCOPY:D /COMPRESS /FFT /LOG+:$backupPath\log\backup_"$now".log
    }
} catch {
    Write-Host "バックアップに失敗しました。"
    Write-Host "エラー内容: $_"
    exit 1
}

このスクリプトは差分や増分バックアップをしていません。もしも、それらのバックアップをする際は、robocopyコマンドを次のようにします。

# 差分、増分バックアップの前のフルバックアップ後に一度だけ実行
attrib -A "$folder" /S

# 差分バックアップの場合
robocopy "$folder" "$backupPath\BackupFiles\$folder\" /MIR /A /MT:8 /R:3 /W:3 /NP /NFL /NDL /NJH /NJS /NS /NC /COPY:DT /DCOPY:D /COMPRESS /FFT /LOG+:$backupPath\log\backup_"$now".log

# 増分バックアップの場合

robocopy "$folder" "$backupPath\BackupFiles\$folder\" /MIR /M /MT:8 /R:3 /W:3 /NP /NFL /NDL /NJH /NJS /NS /NC /COPY:DT /DCOPY:D /COMPRESS /FFT /LOG+:$backupPath\log\backup_"$now".log

オプションとして、差分バックアップの場合は\Aを、増分バックアップの場合は\Mをつけます。また、attribコマンドは、ファイルやフォルダのアーカイブ属性を変更するものです。robocopyで差分や増分バックアップをする際には、このアーカイブ属性を見て、バックアップするフォルダやファイルを選択しています。そのため、フルバックアップ後に、この属性を変更します。この属性は、ファイルの編集時に自動で変更されます。

作成したスクリプトについて、定期的に実行するためには、タスクスケジューラにこのスクリプトを登録します。タスクスケジューラで指定した時間に自動で実行されます。

さいごに

robocopyでバックアップをするスクリプトを作成しました。できれば、差分や増分バックアップをしたかったのですが、ファイルを削除した際の挙動が納得いかなかったので、そこまではしないことにしました。

みなさんの参考になればうれしいです。