Windows batch file tips
(2023.3.3-2024.1.3)
Windows batchファイルは手軽で便利だが,癖があるので,tipsをメモしていこうと思います。以下では,茶色の文字は省略可能
Tips
batファイルの最初に書くべきこと
@echo off
コマンドを表示しない
cd /d %~dp0
batファイルがあるフォルダに作業フォルダを変更
chcp 65001
batファイルの文字コードをUTF-8に変更(これなしの時はShift_JIS(メモ帳では ANSI) で作る)
echo
echo 文字列
文字列を表示する。文字列は,
ダブルコーテーションは偶数個でなければならない(奇数個のダブルコーテーションは表示できない)。
ダブルコーテーションで囲まれた部分はダブルコーテーションを含めてそのまま表示される。
そうでない部分は,
< > | & ^ %
については,それぞれ,リダイレクト,パイプ,コマンド連結,行の継続,変数の頭と解釈される。それぞれを文字として表示したい時は,
^< ^> ^| ^& %%
と書く。
setlocal enabledelayedexpansionされているときは,!も表示されなくなるので,^!とする。
改行のみの行は
echo.
管理者として実行する
powershell start-process コマンド -verb runas
コマンド(やスクリプトxxx.batなど)を管理者として実行する
引数の参照と変数
> batファイル名.bat 引数1 引数2 ...
コマンドプロンプトからbatファイルを起動する。引数1, 引数2, ...は,%1 %2 ...で参照できる。引数は9個まで。%0 はbatファイル名
set 変数名=値
変数に値を代入する。変数はこのコマンド以降有効でbatファイル終了後も残る。
%変数名%
変数の値を参照する
set /p 変数名="文字列"
コマンドラインに文字列を表示して,文字の入力を待ち,入力された文字列を変数に代入する
ファイル名の抽出とダブルコーテーションの制御
引数の参照(%1など)やforの変数(%%aなど)で,%の後ろに~とアルファベットn, x, d, p(それぞれname, eXtension, drive, path)をつけると,アルファベットに応じたファイル名の部分を抽出する:
%~変数名 ダブルコーテーション除去,例:%~0
%~n変数名 ベース名(拡張子を除いたファイル名)例:%~n0
%~x変数名 拡張子,例:%~x0
%~nx変数名 ファイル名(拡張子あり),例:%~nx0
%~d変数名 ドライブレター(例「C:」),例:%~d0
%~p変数名 ドライブレター(例「C:」)を除いたパス,例:%~p0
%~dp変数名 ドライブレターを含むフルパス,例:%~dp0
%~t変数名 タイムスタンプ,例:%~t0
%~z変数名 ファイルサイズ(単位:byte),例:%~z0
関数
call :関数名 引数1 引数2 ...
関数を呼び出す。関数は,batファイルの任意の場所で次のように定義する:
:関数名
処理コード
exit /b
引数1, 引数2, ...は,%1, %2, ...で参照できる。
if文
if 条件 コマンド
または
if 条件 (
コマンド
) else if 条件2 (
コマンド2
) else (
コマンド3
)
else ifブロック(いくつあってもよい),elseブロックは省略可
if文のコマンド部分では,setコマンドは実行されず,if文を抜けると実行される。例えば
if "a"=="a" (
set x=yes
echo %x%
)
だと,「ECHO は <OFF> です。」と表示されるが
if "a"=="a" (
set x=yes
)
echo %x%
なら「yes」と表示さる。if文のコマンド部分でsetを実行したいときは,関数を用いる。
条件は次のように書く。A, Bは,%変数名%,%~数字,または文字列
not "A"=="B"
not exist "A"
"A" xxx "B" xxxは以下の何れか。数値,タイプスタンプの比較ができる
equ 等しい(equal)
neq 等しくない(not equal)
gtr より大きい(greater than)
geq 以上(greater than or equal)
leq 以下(less than or equal)
lss より小さい(less than)
for文
for /d %%a in (ファイル名) do コマンド
ファイル名(/dをつけるとディレクトリ名)をコマンド部分で%%aで参照できる。aは他の英文字でもよい。ファイル名にワイルドカードを使うとマッチする対象すべてにコマンドを実行する。ファイル名は引数の参照で構成してもよい。
リダイレクトとパイプ
コマンド > ファイル名
コマンドの出力をファイルに出力し,画面(標準出力)には表示しない。ファイルが存在する場合は上書きする。
コマンド >> ファイル名
コマンドの出力をファイルに出力し,画面(標準出力)には表示しない。ファイルが存在する場合は追加書きする。
コマンド 2> ファイル名
コマンドのエラーをファイルに出力し,画面(標準エラー)には表示しない。ファイルが存在する場合は上書きする。
コマンド 2>> ファイル名
コマンドのエラーをファイルに出力し,画面(標準エラー)には表示しない。ファイルが存在する場合は追加書きする。
コマンド1 | コマンド2
コマンド1の出力をコマンド2の入力にし,画面(標準出力)には表示しない。
クリップボード
コマンド | clip
コマンドの出力をクリップボードにコピーする。
powershell -command "get-clipboard"
クリップボードの内容を表示する。
perlによる文字列処理
wsl -- perl a.pl < テキストファイル名 > 出力テキストファイル名
perlスクリプトa.plを呼び出して,テキストファイルの文字列を処理して,出力テキストファイルに出力する。wslをインストールしておく必要がある。
a.plは以下のようにbatファイルのechoで作ればbatファイルだけで完結する。茶色の部分を省略すれば,結果は画面に,「| clip」にすれば,クリップボードに出力できる。
文字列\nを改行,\tをタブに置換するperlスクリプトの例
echo #!/usr/bin/perl > a.pl
echo use utf8; >> a.pl
echo use Encode 'encode'; >> a.pl
echo use Encode 'decode'; >> a.pl
echo $xx=""; >> a.pl
echo while ($x = ^<STDIN^>) {$xx .= decode('%2', $x);} >> a.pl
echo $xx =~ s/\\n/\n/g; >> a.pl
echo $xx =~ s/\\t/\t/g; >> a.pl
echo print encode('sjis',$xx); >> a.pl
サンプル集
タイムスタンプの設定
call :setwtime ファイル名1 ファイル名2
ファイル名2のタイムスタンプ(wtime)をファイル名1のタイムスタンプに変更する。
(コード)
:setwtime
powershell Set-ItemProperty '%2' -name LastWriteTime -value '%~t1'
exit /b
テキストファイルの内容を変数にコピー
call :getstr テキストファイル名
テキストファイルの内容を変数strにコピーする。複数行のテキストの場合,改行は\nに置き換える。
(コード)
:getstr
set str=
SET /P str=<%1
for /f "usebackq skip=1 delims=" %%a in (`type "%~1"`) do call :addstr "%%a"
exit /b
:addstr
set str=%str%\n%~1
exit /b