連載
» 2018年03月15日 05時00分 公開

Tech TIPS:Windowsのバッチファイル中で日付をファイル名に使用する (2/2)

[打越浩幸, 島田広道,共著]
前のページへ 1|2       

実際の利用例(バックアップした日がすぐ分かるようにフォルダをバックアップする)

 この手法を利用して、例えばrobocopyコマンドで過去のバックアップを残しつつ、特定のフォルダをバックアップする例を説明しよう。

 バックアップの保存先としては、このバッチファイルを起動したドライブの「\Backup」というフォルダの直下に、バックアップした日付を含む名前のサブフォルダを作成して利用する。これにより過去のバックアップは上書きされずに別々のサブフォルダに保存されていく。

 また、このサブフォルダをどこか別のシステムへコピーして保存することを考え、サブフォルダ名にはサーバ名も含めるようにしている(ファイル名の最後に「-%COMPUTERNAME%」などを付けてコンピュータ名を付加する)。これにより、どのシステムでいつバックアップしたかがすぐに分かるようになる。

※ファイル:backupcmd.cmd

@echo off
setlocal

set backupsrc=c:\datafiles
set drv=%cd:~0,1%
set dt=%date%
set FName=%drv%:\Backup\%dt:~0,4%%dt:~5,2%%dt:~8,2%-%COMPUTERNAME%

robocopy %backupsrc% "%FName%" /mir



 「set drv=%cd:~0,1%」は、カレントドライブを取り出すための指定である。タスクスケジューラで自動起動する場合は、カレントドライブではなく、「C:」や「D:」など、特定のドライブを明示的に指定するのがよい。

 「set dt=%date%」で、いったんdate変数をdtという変数にコピーしているのは、date変数を3回参照している間に日付が変わってしまっても問題がないようにするためである(バッチファイルでは、1行ごとに環境変数の展開処理が行われるので、行が異なると、%date%%time%の値が変わっている可能性がある)。

 このテクニックはdate変数より、むしろtime変数を使う場合に有用だろう。なぜなら、処理に時間がかかるとtime変数の値はどんどん進んでしまい、不整合が生じる可能性があるからだ。

 なお、「%date%」を実行してから「%time%」を実行するまでの間に日付が変わる可能性もわずかながらある。それが心配なら、次のようにif文を追加で実行して、「%date%」を再取得するとよいだろう(日付をまたぐような時間帯には実行させないという対処方法もある)。

set dt=%date%& set tm=%time%
if "%tm:~0,5%"==" 0:00" set dt=%date%

※00時00分の場合は、日付が前日の可能性があるので再取得する



1日前の日付を求める計算

 以上の例では、今日の日付を取り出してフォルダ名の一部に用いている。しかし実際には、前日や1カ月前の日付が欲しい場合も少なくない。例えば前日の日付を名前として持つログファイルを別のサーバへコピーしたり、1カ月前のファイルを見つけ出して削除したり、といったケースが考えられる。

 だが残念なことにバッチファイルでは、1日前や1カ月前を計算して、変数にセットする簡単な方法はない。

 一応「set /a」コマンドを使えば数値計算もできるので、日付部分を1日前に戻すといった操作も不可能ではない。しかし、月の初めや年の初め、うるう年の2月末日の処理なども考慮しなければならないので、非常に面倒である。

 あえてバッチファイルで書くとすると、次のようになるだろうか。

※ファイル:prevdate.cmd

@echo off
setlocal

set dt=%date%
set yy=%dt:~0,4%
set mm=%dt:~5,2%
set dd=%dt:~8,2%

echo 今日は%yy%年、%mm%月、%dd%日です。
echo.

rem 1日前の日付を計算する

set /a dd=1%dd%-101
set dd=00%dd%
set dd=%dd:~-2%
set /a ymod=%yy% %% 4

if %dd%==00 (
  if %mm%==01 ( set mm=12 & set dd=31 & set /a yy=%yy%-1 )
  if %mm%==02 ( set mm=01 & set dd=31 )
  if %mm%==03 ( set mm=02 & set dd=28 & if %ymod%==0 ( set dd=29 ) )
  if %mm%==04 ( set mm=03 & set dd=31 )
  if %mm%==05 ( set mm=04 & set dd=30 )
  if %mm%==06 ( set mm=05 & set dd=31 )
  if %mm%==07 ( set mm=06 & set dd=30 )
  if %mm%==08 ( set mm=07 & set dd=31 )
  if %mm%==09 ( set mm=08 & set dd=31 )
  if %mm%==10 ( set mm=09 & set dd=30 )
  if %mm%==11 ( set mm=10 & set dd=31 )
  if %mm%==12 ( set mm=11 & set dd=30 )
)

echo 1日前は、%yy%年、%mm%月、%dd%日です。



 だが、ここまでしてわざわざバッチファイルで計算するのは、あまり勧められない。2日前や3カ月前にするといった応用が利かないからだ。こういった場合はPowerShellやWSHで処理する方が簡単だろう。

 ここでは詳しく解説しないが、例えばPowerShellでは、年月日を数字にするなら「(Get-Date).ToString("yyyyMMdd")」とするだけだ。1日前を求めるには、日付を加減算するAddDays()メソッドを使って「(Get-Date).AddDays(-1).ToString("yyyyMMdd")」とすればよい。

■更新履歴

【2018/03/15】最新OSに合わせて内容を更新しました。

【2015/07/01】Windows 8/Windows 8.1/Windows 10/Windows Server 2012/Windows Server 2012 R2に対応しました。

【2004/05/01】初版公開。


「Tech TIPS」のインデックス

Tech TIPS

前のページへ 1|2       

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。