バッチファイルのクソ仕様にやられたので備忘録まとめ
はじめに
業務で普段使いするバッチプログラムをまとめて書いてみた。
ANDとORとbreakとcontinueできないので不満が多い言語
AND
10分後の時刻を取得する処理
現在時刻を分に直し、10分足して剰余演算する処理
バッチは言語仕様によりif文が煩雑になりがち
如何にテスト工程数を減らすかが肝
@echo off
setlocal enabledelayedexpansion
:: 現在時刻をUNIX時間っぽく処理する
for /f "tokens=1-2 delims=:" %%a in ("%time%") do (
set /a totalMin=%%a * 60 + %%b + 10
)
set /a hh=totalMin / 60 %% 24
set /a mm=totalMin %% 60
:: ゼロパディング
if !hh! LSS 10 set hh=0!hh!
if !mm! LSS 10 set mm=0!mm!
set starttime=!hh!:!mm!
echo %starttime%
タスクスケジューラに新規タスクを登録する処理
schtasks /createコマンド
これ自体は普通の処理
ターミナルに入力する場合は改行せずに1行で新規登録できるが、ファイルに書き込むときは改行しないとうまく動作しない場合もある
/trの引数のパスにダブルクォートやスペースが入るとバッチが正しく認識しなくなる
しかしパスの部分には変数を使いたい場合が多く、いちいち考慮していられない
そこで、/trにコマンドラインのパスを渡してあげる
rem タスク作成ログ出力
schtasks /create /tn "MyTask" ^
/tr "\"cmd.exe\" /c \"C:\path with spaces\my_script.bat\"" ^
/sc once /st 12:00
↑/trの解釈をコマンドラインに任せることで安定して動作できる
コマンド実行時にエラーメッセージがでる場合はスルーする
@echo off
setlocal enabledelayedexpansion
schtasks /query /tn !taskname! 2>nul
if !errorlevel! equ 0 (
schtasks /delete !taskname! /f
)
1行目で!taskname!に一致するタスク名をクエリする。
タスクが存在しなければエラーメッセージがターミナルに表示されるが、
2>nulを末尾につけることでエラーメッセージをスルーできる。
1>nulにすると成功メッセージをスルーできる。
FOR文の書き方 + if文
残念ながらJavaのstreamやforEach,拡張for文に当たるものはない。
基本for文のみ解説する。
@echo off
setlocal enabledelayedexpansion
for /f "usebackq tokens=*" %%f in ("C:\User\sample.csv") do (
echo /y %%f >> "C:\User\result.csv"
if !ERRORLEVEL! neq 0 (
echo %DATE% %TIME% ERR %DEF_NAME% "COPY 異常終了" >> %ALERT_LOG%
)
)
"C:\User\sample.csv"のデータを1行ずつfor文を回して取得し、
"C:\User\result.csv"にコピーする処理。
%%fは変数。
if-else文をスマートに記述する
@echo off
setlocal enabledelayedexpansion
cmd "dummy" && (
// process A
ver >nul
) || (
// process B
)
cmd "dummy"が成功 ⇒ process A が走る
cmd "dummy"が失敗 ⇒ process B が走る
ver >nulは必ず成功するダミーコマンド
ver: Windowsのバージョン表示コマンド / 通常、ERRORLEVEL 0
ver >nulで「必ず成功するコマンドの表示を捨てる」
ver >nulがない場合
@echo off
setlocal enabledelayedexpansion
cmd "dummy" && (
// process A
) || (
// process B
)
このように、
process Aの成否にかかわらずprocess Bが実行されてしまう。
おわり
cipher /w:C:\
ドライブ上の未使用領域(削除済みファイルの断片が残る可能性のある領域)を、00→FF→ランダムの順で3回上書き
Discussion