#【DOS】使える時に使いたいバッチ(bat)のコード
令和の時代にbatファイルで悩みたくもない。
DOSでヨクアル処理を組むときのコードのサンプルです。
必要にかられて、ほうぼうで調べてきたり自力で組んでいたものをここにメモします。
説明は適当なので詳細はコマンド名で調べてください。
適当に追記予定です。
起動テンプレ
先頭に書く定型句。
@ECHO OFF
SETLOCAL
SET BASE_DIR=%~dp0
CD /d "%BASE_DIR%"
ECHOを切る、環境変数をローカルに分離する。
%~dp0
はbatファイルがあるフォルダのことで、環境変数%BASE_DIR%
に格納後カレントを移動。
batファイルをダブルクリックして動かすと元からカレントが同フォルダになりますが、その後、自動化のためにタスクスケジューラに登録したりするとカレントが違っていてアレってなります。
もちろん移動しない方が楽な事もあります。
スペースを含むファイル名はbatではやっかいな存在です。
変数にダブルクォートをつけて格納するか、入れずにコマンド実行時に毎回付けるか。私は入れない派ですけど、どんなもんでしょうか。
終了テンプレ
最後に書く定型句。
ENDLOCAL
EXIT /b 0
開始テンプレと対になります。
EXITには/b 0
を付けておかないと、自動化する際に躓きます。(CALLされた時、EXITだけだと呼び出した元バッチごと終了してしまいます)
引数のファイル名を取得
SET TARGET_FILEPATH=%~1
SET TARGET_DIR=%~dp1
SET TARGET_FILE=%~nx1
SET TARGET_FILE_NOEXT=%~n1
echo file : "%TARGET_FILEPATH%"
echo file : "%TARGET_DIR%"
echo file : "%TARGET_FILE%"
echo file : "%TARGET_DIR%bat_%TARGET_FILE_NOEXT%_output.txt"
第1引数は%1
で取れます。対象のファイルをbatファイルにドロップしたときもここに入ります。
ただ、ドロップしたとき、ファイル名やフォルダ名にスペースが有ると前後にダブルクォートが付き、無い場合は付きません。
なので、ここでは%~1
としてダブルクォートがあれば外すようにしています。変数に入るのは、クォート無しで確定です。
%~dp0
がバッチファイルの場所を表すのと同様、%~dp1
で引数のファイル名があるフォルダが取れます。
(この時、末尾には\マークが入ります)
%~nx1
でパスを除いたファイル名が取れます。正確にはxが拡張子、nが拡張子無しのファイル名です。
%~n1
が拡張子無しになるので適当に接頭語・接尾語をつければ簡単に出力ファイル名が作れますね。
数秒待機する
TIMEOUT 1 > nul 2>&1
Win7以降はtimeoutコマンドが使えます。
X秒待ちますの出力を隠すためにnulに送っています。
PAUSEコマンドを使うと止まっちゃうので私はこちらのほうが好き。
無いフォルダを作る
IF NOT EXIST "%BACKUP_DIR%" (
MKDIR "%BACKUP_DIR%"
)
こう作ろうとは言われていますけれど、存在するフォルダを作ろうとしてもmkdirがエラー吐くだけなのでホントに要るかは分かりません。
現在日付を取得
SET DATE_STRING=%date:~-10,4%%date:~-5,2%%date:~-2,2%
ECHO %DATE_STRING%
YYYYMMDD形式。2021/05/05を20210505みたいな形に。
よく見られた構文ですが、dateの書式はロケールに依存するため
海外のOSでは使えないことがあります。
現在時刻を取得
SET time0=%time: =0%
SET TIME_STRING=%time0:~0,2%%time0:~3,2%%time0:~6,2%
ECHO %TIME_STRING%
同じですが、timeコマンドはゼロ埋めされないのでひと手間が掛かります。
曜日を取得
ECHO WScript.Quit (Weekday(Now)+100) > wday.vbs
SET WDAY=None
CScript //Nologo wday.vbs
IF ERRORLEVEL 101 SET WDAY=Sunday
IF ERRORLEVEL 102 SET WDAY=Monday
IF ERRORLEVEL 103 SET WDAY=Tuesday
IF ERRORLEVEL 104 SET WDAY=Wednesday
IF ERRORLEVEL 105 SET WDAY=Thursday
IF ERRORLEVEL 106 SET WDAY=Friday
IF ERRORLEVEL 107 SET WDAY=Saturday
ECHO %WDAY%
DOSコマンドでは曜日を扱えないので、VBScriptを使うのが良いとされています。
と言いながらwday.vbsは1行なのでechoでその場で作っています。もちろん、wday.vbsを別途用意する、一回作った後はechoをコメントアウトするとかしたほうがお行儀は良いです。
+100しているのはwday.vbsが無かった時にCScriptが1を返してしまうようなので。(CScriptの戻り値については探しても見つからない;
現在日付を取得その2
echo WScript.Quit Year(Now)*10000+Month(Now)*100+Day(Now) > datestring.vbs
CScript //Nologo datestring.vbs
SET DATE_STRING=%ERRORLEVEL%
echo %DATE_STRING%
日付をVBScriptで取るとこう。
こちらはロケール依存しないかも。‥‥といっても海外OSでは試していないし、戻り値を直接使っているので普通のエラー処理ができないですね。
ファイル一覧を表示
DIR /b
今更ですが/b
を使うとファイル名だけが取れます。
今でもフォルダ内のファイル名一覧を取りたい時はDIR /b > list.txtとかやります。
DIR *.png /b
フィルタリングできることは忘れがち。
ファイルを検索する
forfilesを使うといろんなことができます。
基本構文
FORFILES /M *.txt /S
FORFILES /P target /M *.txt /S
FORFILES /M *.txt /D -30 /S
/S
でサブフォルダ内も探す。
/M *.*
で探すファイルを指定する。
/P フォルダ名
でここでないフォルダから探索できる。
/D 数値
でその日数以前の最終更新日時のファイルを探せる。
FORFILES /M *.txt /S /C "cmd /c echo @path"
コマンドプロンプト上で検索を掛けるならあれで十分ですが、
/Cを使うと見つけたファイルに対してコマンドが発行できます。
もちろん、ただechoするだけなら一緒ですが、
1カ月前のファイルを削除
FORFILES /M *.txt /D -30 /S /C "cmd /c del /Q @path"
delコマンドを発行すればクリーニング処理が1行でできます。
batファイルを実行
ファイル名を引数としたbatファイルが実行できればたいていの事ができますね。
SET ACTION=%BASE_DIR%sub.bat
FORFILES /M *.csv /S /C "cmd /c;\"%ACTION%\" @path"
@echo file : %~1
@exit /b 0
FORFILESの探索中はカレントが探索中のフォルダになるようなので、実行ファイルはフルパスで指定したほうが無難です。
cmd /c
でダブルクォートで囲ったファイルを実行するには、/c
の後に;
を付けるといいようです。(なんでそうなるかは難解ですが‥‥)
一方、@path
のほうは元からダブルクォート済みでバッチ側に渡ります。%~1
の式で外してしまえばOKです。
VBScriptを実行
SET ACTION=%BASE_DIR%sub.vbs
FORFILES /M *.txt /S /C "cmd /c cscript /Nologo \"%ACTION%\" @path"
parm1 = WScript.Arguments(0)
WScript.Echo(parm1)
WScript.Quit 0
cscriptコマンドを発行すればVBScriptが起動できるのでもっと色んな事ができますね。
あと必要なときに加筆予定
独学のため正確でない可能性があります。
(っ・x・)っ きゅ