任意ディレクトリをRobocopyの速さを生かして世代管理するバッチを書いた
Robocopyって同期出来るから速いじゃん?
バックアップなんだから世代管理したいじゃん?
あれ、矛盾してね?
前置き
以前書いたRobocopyの記事。
Robocopyのオプションについてはこちらを参照下さい。
nyanshiba.hatenablog.com
Robocopyの/MIR
で同期のようなバックアップが出来るため、コピー先が同じディレクトリであれば2回目以降はとても早くバックアップできる。
それを利用しつつ、世代管理もしようってのがこのバッチ。
指定数世代が溜まったら、古いフォルダからリネームされ、そこへ高速でバックアップされるようになる。
バッチ
@echo off rem --------------------環境変数設定-------------------- rem コピー先のフォルダを残す数を指定 set dst_num=5 rem コピー先ディレクトリを指定 set "dst=G:" rem --------------------フォルダ名の日付時刻-------------------- rem yyMMdd_Hmm rem 自分用(17/08/30 (水) 17:35->170830_1735) set mydate=%date:~0,2%%date:~3,2%%date:~6,2%_%time:~0,2%%time:~3,2% rem 初期設定(2017/08/30 17:35 -> 170830_1735) rem set mydate=%date:~2,2%%date:~5,2%%date:~8,2%_%time:~0,2%%time:~3,2% rem スペースを0に置き換える set mydate=%mydate: =0% rem --------------------フォルダ作成-------------------- rem dirでコピー先のフォルダをフォルダ名のみ日付順で表示し、新しい方からdst_num個飛ばし、該当フォルダがあれば削除する for /f "skip=%dst_num%" %%a in ('dir "%dst%" /ad-s /b /o-n') do ( echo 削除:"%dst%\%%a" rd /s /q "%dst%\%%a" ) rem dirでコピー先のフォルダをフォルダ名のみ日付順で表示し、新しい方からdst_num-1個飛ばし、該当フォルダがあればリネーム set /a dst_num1=dst_num-1 for /f "skip=%dst_num1%" %%a in ('dir "%dst%" /ad-s /b /o-n') do ( ren "%dst%\%%a" "%mydate%" echo コピー先:%dst%\%mydate%^(差分:%dst%\%%a^) ) rem コピー先に名前が変数mydateなフォルダが無ければ作成 if not exist "%dst%\%mydate%" ( md "%dst%\%mydate%" echo コピー先:%dst%\%mydate%^(新規^) ) rem --------------------ログ作成-------------------- rem コピー先に概要ログを作成 echo %mydate% >> "%dst%\robocopy_summary.txt" rem --------------------robocopy-------------------- rem コピー元ディレクトリを指定 set "src=C:\hoge" rem コピー先サブディレクトリを指定 set "dst_sub=\hoge" rem robocopyサブルーチンを実行 call :copysub echo 処理終了 pause exit :copysub rem --------------------robocopyサブルーチン-------------------- echo %src%^-^>%dst%\%mydate%%dst_sub% rem 詳細ログがコピー先のフォルダ内に出力される robocopy "%src%" "%dst%\%mydate%%dst_sub%" /MIR /XO /NP /XA:SH /R:3 /W:5 /LOG+:"%dst%\%mydate%\robocopy_details.txt" /XD "C:\DTV\backupandsync" "C:\DTV\ts" /FFT exit /b
解説
コピー先のディレクトリ構造
dst ┣mydate ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┗robocopy_details.txt ┣mydate ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┗robocopy_details.txt ┣mydate ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┣dst_sub ┃ ┗robocopy_details.txt ┗robocopy_summary.txt
コピー先を決める仕組み
1.コピー先のフォルダ数が一定より大きい:古い方から該当フォルダを削除
フォルダを残す数dst_numを小さい値に変更した際、2.が実行されてしまうのを防ぐ役割も担っている。
rem dirでコピー先のフォルダをフォルダ名のみ日付順で表示し、新しい方からdst_num個飛ばし、該当フォルダがあれば削除する for /f "skip=%dst_num%" %%a in ('dir "%dst%" /ad-s /b /o-n') do ( echo 削除:"%dst%\%%a" rd /s /q "%dst%\%%a" )
例:フォルダを5個残す場合、コピー先にフォルダが7個あれば、古い方から2個削除し5個に
dst ┣180204 <-削除 ┣180211 <-削除 ┣180218 ┣180225 ┣180304 ┣180311 ┗180318 ↓ dst ┣180218 ┣180225 ┣180304 ┣180311 ┗180318
2.コピー先のフォルダ数が一定以上:最も古いフォルダを現在の日付にリネームして、そこにバックアップ
rem dirでコピー先のフォルダをフォルダ名のみ日付順で表示し、新しい方からdst_num-1個飛ばし、該当フォルダがあればリネーム set /a dst_num1=dst_num-1 for /f "skip=%dst_num1%" %%a in ('dir "%dst%" /ad-s /b /o-n') do ( ren "%dst%\%%a" "%mydate%" echo コピー先:%dst%\%mydate%^(差分:%dst%\%%a^) )
例:フォルダを5個残す場合、コピー先にフォルダが5個あれば、最も古いフォルダを現在の日付にリネームし、そこに差分コピー
dst ┣180218 <-リネーム ┣180225 ┣180304 ┣180311 ┗180318 ↓ dst ┣180325 ┣180225 ┣180304 ┣180311 ┗180318
3.コピー先のフォルダ数が一定未満:現在の日付のフォルダにバックアップ
rem コピー先に名前が変数mydateなフォルダが無ければ作成 if not exist "%dst%\%mydate%" ( md "%dst%\%mydate%" echo コピー先:%dst%\%mydate%^(新規^) )
例:フォルダを5個残す場合、コピー先にフォルダが5個以上無ければ、現在の日付のフォルダがされ、そこにコピー
dst ┣180304 ┣180311 ┗180318 ↓ dst ┣180304 ┣180311 ┣180318 ┗180325 <-作成
使い方
1.バッチをテキストエディタにコピペし、拡張子.bat、文字コードShift-JIS(ANSI)で保存。
※ファイル名はrobocopy
以外
2.以下を自分の環境や目的に合わせて変更する。
rem --------------------環境変数設定-------------------- rem コピー先のフォルダを一定数残す数を指定 set dst_num=5 rem コピー先ディレクトリを指定 set "dst=G:"
・dst_num
世代管理する際、何世代残すかを指定する。
大きなファイルを扱う場合には、ストレージの容量を超えないように調整すること。
・dst
コピー先の元ディレクトリを指定。
スペースや記号等が入るディレクトリでは、"set dst=G:"
のように囲うこと。
rem --------------------robocopy-------------------- rem コピー元ディレクトリを指定 set "src=C:\hoge" rem コピー先サブディレクトリを指定 set "dst_sub=\hoge" rem robocopyサブルーチンを実行 call :copysub
・src
コピー元ディレクトリを指定
・dst_sub
コピー先サブディレクトリを指定
src=C:\hoge
、dst=G:
、mydate=180322_2249
、dst_sub=\hoge
の場合、コピー元はC:\hoge
、コピー先はG:\180322_2249\hoge
となる。
set dst_sub=
でコピー先はG:\180322_2249
となる。
・call :copysub
上記内容でRobocopyを呼び出す
rem --------------------robocopy-------------------- set "src=C:\hoge" set "dst_sub=\hoge" call :copysub set "src=C:\bin\foo" set "dst_sub=\foo" call :copysub set "src=D:\fuga" set "dst_sub=\fuga" call :copysub
とすると、このように任意のディレクトリに対してそれぞれバックアップすることができる。
コピー元C:\hoge
、コピー先G:\180322_2249\hoge
コピー元C:\bin\foo
、コピー先G:\180322_2249\foo
コピー元D:\fuga
、コピー先G:\180322_2249\fuga
:copysub rem --------------------robocopyサブルーチン-------------------- echo %src%^-^>%dst%\%mydate%%dst_sub% rem 詳細ログがコピー先のフォルダ内に出力される robocopy "%src%" "%dst%\%mydate%%dst_sub%" /MIR /XO /NP /XA:SH /R:3 /W:5 /LOG+:"%dst%\%mydate%\robocopy_details.txt" /XD "C:\DTV\backupandsync" "C:\DTV\ts" /FFT exit /b
・robocopy "%src%" "%dst%\%mydate%%dst_sub%"
の後にオプションを書く。お好みに。
・/LOG+:"%dst%\%mydate%\robocopy_details.txt
で詳細ログがコピー先のフォルダ内に出力される。
3.実行
・バッチファイルをダブルクリック
・タスクスケジューラに登録する
etc.