汝、コマンドプロンプトを愛せよ
Windowsの自動化の基本となるものにコマンドプロンプトと、そこから実行できるバッチファイルがあります。
Windowsのバッチファイルは古いマシンから新しいマシンまで使用できます。
今回は、それをまとめてみようと思いますが、百番煎じくらいになるので、なるべくMicrosoftが提供するドキュメントをベースになるように話を進めたいと思います。
文中のリンクは基本的に公式サイトへのリンクになっているので必要に応じて参照してください。
※注意
なにがなんでもバッチファイルで書けという趣旨の記事ではありません。最近はPowerShellも使えますし、レガシーの環境ではWSHという選択肢もあります。
汝、ヘルプを愛せよ
コマンドプロンプトでなんらかの操作を行う場合、手っ取り早くコピペですますのもよくあることですが、基本的にはヘルプを確認するようにしましょう。コピペ元のコマンドやオプションをよくわからないままつかって、動かなかったり、ひどい目にあうことは、よくあることです。
結局、自分自身がこれから行う作業にとって、実行するコマンドやオプションが適切かどうか判断するには公式が提供するヘルプをみるしかないのです。
では、そのとっかかりとして、コマンドプロンプトで以下のコマンドを実行してみましょう。
help
コマンドプロンプトで使用できる主だったコマンドの一覧が取得できると思います。
ここで特定のコマンドの詳細を確認したい場合は以下のようにhelpの後にコマンド名を実行します。
help dir
dirコマンドの詳細の使い方が表示されました。
helpコマンドはコマンドプロンプトやバッチファイルで使用するコマンドの詳細を表示してくれます。しかしながら、すべてのコマンドのヘルプをサポートしているわけではありません。
もし、「help コマンド名」でヘルプが表示されなかったら「コマンド名 /?」を実行してみてください。
ヘルプで不十分だった場合は?
実際のところ、helpコマンドで表示されるヘルプに全ての情報がのっているわけではありません。
次に読むべきものはMicrosoftが提供するドキュメントです。
たとえば、以下からコマンドのリファレンスのリンクが存在します。
Microsoftが提供するインターネット上のドキュメントは昨今、機械翻訳になっていたり、そもそも日本語対応していなかったり、数年たったらなんか消えている場合があったりしますが、もっとも尊重すべきドキュメントの一つです。
この文章を含めた個人サイトを読むのは、あくまでおまけとして、公式が何を言っているかをつかむようにしましょう。
コマンドプロンプトの起動方法
コマンドプロンプトは「Winキー+R」を押した後に「cmd.exe」と入力すると起動します。
ここではコマンドプロンプトの起動についての話をいくつかしようと思います。
特定のディレクトリをカレントディレクトリとしてコマンドプロンプトを起動したい
たとえば、特定のディレクトリをカレントディレクトリとしてコマンドプロンプトを起動したい場合がよくあると思います。
その場合はショートカットを使用すると楽です。
6.以後ショートカットを起動すると、ショートカットを作成したディレクトリをカレントディレクトリとしてコマンドプロンプトが起動します。
もし、このショートカットでの起動時に特定のコマンドを実行したい場合はリンク先を以下のように記載します。
%windir%\system32\cmd.exe /k C:\dev\python3\py3env.bat
kオプションの後に実行したいバッチファイルを指定してください。
指定したバッチファイルを実行した後に、コマンドプロンプトが操作可能になります。
これは特定の環境変数を定義してあるコマンドプロンプトを使用するのに便利なテクニックになります。
起動したコマンドプロンプトすべてで初期処理を実行したい場合
下記のレジストリに実行したいバッチファイルのパスを記載することで起動時の初期処理を記載できます。
- HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun
- HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun
HKEY_LOCAL_MACHINEはローカルPCすべてのユーザで実行される処理で、HKEY_CURRENT_USERは現在のユーザのみで実行される処理になります。
実行順番としてはHKEY_LOCAL_MACHINE→HKEY_CURRENT_USERとなります。
cmd.exeを実行する場合にdオプションをつけることで、AutoRunを無視することが可能です。
REM 初期処理が実行してからt.batが動作する
cmd /c t.bat
REM 初期処理が実行されないでt.batが動作する
cmd /d /c t.bat
コマンドプロンプトの操作
履歴操作
コマンドラインで実行したコマンドは履歴として保持しており、再実行することが可能です。
F7キーによる履歴の表示
またカーソルを上下にうごかして、Enterキーを押すことで、再実行が可能になっています。
doskeyコマンドによる履歴の表示
doskeyコマンドのhistoryオプションを使用することで履歴の一覧が表示されます。
doskey /history
カーソルキーとPageUp、PageDownによる履歴の選択
キーボード | 説明 |
---|---|
↑ | 現在表示されている前の履歴のコマンドを実行します |
↓ | 現在表示されている後の履歴のコマンドを実行します |
PageUp | 履歴の最古のコマンドを呼び出します |
PageDn | 履歴の最新のコマンドを呼び出します |
カーソルキーの↑または↓を押下することで過去の履歴を選択することが可能です。
前方一致による履歴の選択
過去に実行したコマンドを途中まで入力した時点でF8を押下すると過去の履歴から前方一致するコマンドを実行します。複数ある場合は、もう一度F8を押下することで切り替えられます。
履歴の番号による選択
F9を入力することで数値で履歴を選択できます。
履歴の消去
Alt+F7で履歴をすべて消去します。
マクロ
doskeyコマンドを使用することでマクロを登録可能です。
これにより複数の操作を一つのコマンドで実行したり、PowerShellでいうようなAliasのような使い方ができます。
なお、下記のヘルプにあるようにコマンドのヘルプにあるようにdoskeyコマンドで作成したマクロはバッチファイルから実行できません。
Running a doskey macro
To run a macro, type the macro name at the command prompt, starting at the first position. If the macro was defined with $\* or any of the batch parameters $1 through $9, use a space to separate the parameters. You cannot run a doskey macro from a batch program.
マクロの登録
コマンドでの登録
doskeyコマンドにマクロ名とコマンド名を指定することで使用することでマクロを登録することが可能です。
以下はWindowsのコマンドプロンプトでlsをサポートする場合の例になります。
doskey ls=dir $*
$*はパラメータを意味して以下のようなコマンド実行が可能になります。
ls /s c:\
$tを使用することで複数のコマンドを実行することが可能になります。
doskey prog=echo %ProgramFiles(x86)%$techo %ProgramFiles%
登録されたマクロはコマンドプロンプトを終了するまで有効になります。
また先に述べたようにdoskeyコマンドの制約のため、マクロをバッチファイル中で使用することはできませんが、バッチファイルで登録は可能です。
ファイルで登録
doskeyコマンドの/MACROFILEオプションを使用することでファイルからマクロを登録できます。
まず以下のようなファイルを用意します。
ls=dir $*
t=echo test
このファイルを用いてファイルを登録するには以下のようにします。
doskey /MACROFILE=C:\dev\bat\macro.txt
マクロの一覧表示
doskeyコマンドに/macrosオプションを付与することで現在登録中のマクロの一覧を取得できます。
REM マクロをすべて表示
doskey /macros
マクロの削除
Alt+F10で登録されているマクロが削除されます。
Windows10での新機能
コマンドプロンプトはバージョンアップを続けており、Windows10やWindowsServer2016では新しい機能が色々とサポートされています。
What's New in the Windows Console in Windows Server 2016 Technical Preview
https://docs.microsoft.com/en-us/previous-versions/orphan-topics/ws.11/mt427362(v=ws.11)?redirectedfrom=MSDN
【まとめ】Windows 10で強化/追加されたコマンドプロンプトの機能
https://www.atmarkit.co.jp/ait/articles/1508/28/news038.html
さらに一部の文字を色を変更して出力することも可能になっています。
echo <ESC>[34mtest<ESC>[0m
※にはESCの文字コード「0x1B」を入力してください。
How to echo with different colors in the Windows command line
https://stackoverflow.com/questions/2048509/how-to-echo-with-different-colors-in-the-windows-command-line
バッチファイル
バッチファイルの実行方法
拡張子batのファイルをエクスプローラーからダブルクリックするか、コマンドプロンプトで以下のように実行するとバッチファイルが実行できます。
たとえば以下のようなバッチファイルが存在します。
echo sub.bat.....
これを実行するには以下のようにします。
C:\dev\bat\func>C:\dev\bat\func\sub.bat
C:\dev\bat\func>echo sub.bat.....
sub.bat.....
バッチファイルを実行すると、バッチファイル内のコマンドがコマンドプロンプトに表示されてしまいます。
バッチファイル内のコマンドをコマンドプロンプトに表示しないようにするには行の先頭に@を付与します。
@echo sub.bat.....
このバッチファイルを実行すると@を付けたコマンドがコマンドプロンプトに表示されていないことが確認できます。
C:\dev\bat\func>C:\dev\bat\func\sub.bat
sub.bat.....
大量のコマンドがある場合、いちいち@を付けるのは面倒です。
この場合、echoコマンドを使用してコマンドエコー機能をオフにします。
@echo off
echo sub.bat.....
バッチファイル中から別のバッチファイルを実行する
バッチファイルの中から別のバッチファイルを実行する場合はcallコマンドを使用します。
@echo off
echo 呼び出し前
call sub.bat
echo 呼び出し後
これを実行すると以下のようになります。
>main.bat
呼び出し前
sub.bat.....
呼び出し後
もし以下のようにcallコマンドを使用せずにバッチを実行した場合、呼び出し元の処理に戻りません。
@echo off
echo 呼び出し前
sub.bat
echo 呼び出し後
>main.bat
呼び出し前
sub.bat.....
バッチファイル内のラベル
バッチファイル内に「:」を使用してラベルを宣言することが可能です。
ラベルにはgotoコマンドをジャンプすることができます。
@echo off
echo p1
goto label1
echo p2
:label1
echo p3
上記のバッチファイルを利用するとgotoで指定したラベルに処理がジャンプすることが可能です。
>label.bat
p1
p3
指定したラベルはcallコマンドを使用することで関数のように使用することが可能です。
@echo off
call :label2
echo p4
exit /b
:label2
echo p5
exit /b
上記のバッチファイルの実行結果は以下のようになります。
>label2.bat
p5
p4
p4をエコーする前にlabel2にジャンプしてp5をエコーしていることが確認できます。
コメントの使用方法
remコマンドを使用することでコメントを使用することができます。
REM コメント1 (コマンドがエコーされます)
@REM コメント2 (コマンドがエコーされません)
ラベルを利用したコメント
以下のようにラベル(:)を利用したコメントの方法が紹介されている場合があります。
::コメント
これはあくまでラベルを利用したトリックでマイクロソフトで公式のドキュメントで定義されたコメントの仕様ではありません。
たとえば以下のケースではエラーになります。
@echo off
IF EXIST C:\ (
:: Comment line 1
ECHO Do something
:: Comment line 2
)
下記のページではラベルを使用したコメントについて制限や複数行コメントについてのトリックが述べられています。
Rob van der Woude's Scripting Pages -Comments-
https://www.robvanderwoude.com/comments.php
別プロセスでバッチファイルを実行する
別プロセスでバッチを実行するにはstartコマンドを利用します。
REM 非同期で実行
start cmd.exe /c sleep.bat
REM 同期で実行
start /wait cmd.exe /c sleep.bat
バッチファイルの終了コード
exitコマンドを使用することで、バッチファイルの終了コードを指定できます。
終了コードは環境変数ERRORLEVELに格納されます。
@echo off
echo main
exit /b 9999
>test.bat
main
>echo %ERRORLEVEL%
9999
/bオプションを付けないで実行するとcmd.exeが終了します。
バッチファイルのパラメータ
バッチファイルはパラメータを使用することができ、バッチファイル中に環境変数を利用してパラメータを参照することができます。
バッチファイル内でパラメータを利用するには%1~%9を使用します。
@echo off
echo sub.bat..... %1 %2 %3
バッチファイルをパラメータ付きでよびだすには、パラメータを空白、「,」、「;」で区切ります。
>sub.bat abc def jh
sub.bat..... abc def jh
>sub.bat abc,def,jh
sub.bat..... abc def jh
>sub.bat abc;def;jh
sub.bat..... abc def jh
複数コマンドの実行
バッチファイルやコマンドは条件付き処理記号を使用して実行することができます。
文字 | 構文 | 定義 |
---|---|---|
& [...] | Command1 &Command2 | 単一のコマンド ライン上の複数のコマンドを区切るために使います。1 つ目のコマンドが実行された後に、2 つ目のコマンドが実行されます。 |
&& [...] | Command1 &&Command2 | && 記号の前にあるコマンドが正常に終了した場合にのみ、後ろにあるコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが正常に終了した場合にのみ、2 つ目のコマンドが実行されます。 |
|| [...] | Command1 || Command2 | || 記号の前にあるコマンドが失敗した場合にのみ、後ろにあるコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが失敗した場合 (コマンドから返されるエラー コードが 0 よりも大きい場合) にのみ、2 つ目のコマンドが実行されます。 |
( ) [...] | ( Command1 & Command2) | 複数のコマンドをまとめたり、ネストするときに使います。 |
条件付き処理記号の使用例を以下に記述します。
@echo off
echo ok.bat
exit /b 0
@echo off
echo ng.bat
exit /b 1
>REM &の使用例
>call ok.bat & call ng.bat
ok.bat
ng.bat
>call ng.bat & call ok.bat
ng.bat
ok.bat
>REM &&の使用例
>call ok.bat && call ng.bat
ok.bat
ng.bat
>call ng.bat && call ok.bat
ng.bat
>REM ||の使用例
>call ok.bat || call ng.bat
ok.bat
>call ng.bat || call ok.bat
ng.bat
ok.bat
>REM ()の例
>(call ok.bat || call ok.bat) && (call ng.bat)
ok.bat
ng.bat
リダイレクト
リダイレクト演算子を使って、既定の場所から別の場所に、コマンドの入出力ストリームをリダイレクトできます。
エラー出力
コマンドの出力には標準出力とエラー出力の2種類があります。
多くのコマンドは正常に終了した場合は標準出力に出力し、エラー終了した場合はエラー出力に出力します。
echoコマンドを使用する標準出力に出力しますが、以下のようにすることで標準出力の内容をエラー出力に出力することが可能です。
echo error 1>&2
出力のリダイレクト
ほとんどのコマンドの出力はコマンドプロンプトのウィンドウに送ります。
「>」演算子を使用することで出力をファイルに送ることができます。
以下のコマンドはdirコマンドの出力結果をret.txtファイルに送ります。
dir > ret.txt
もし存在しないパスを選択してエラーになった場合、dirコマンドはエラー出力に出力しますが、これをファイルに送るには以下のようにします。
dir z:\ 2> error.txt
ファイルに出力際に「>>」演算子を使用することでファイルの末尾に出力することができます。
echo test1 > ret.txt
echo test2 >> ret.txt
この結果で出力されるファイルは以下のようになります。
test1
test2
入力のリダイレクト
キーボードからの入力をファイルからリダイレクトするには「<」演算子を使用します。
たとえばsortコマンドはキーボードから入力した内容を昇順に並び替えることができますが、これをファイルから入力するには以下のようにします。
たとえば以下のようなファイル「test.txt」が存在したとして、その内容を並び替かえる例を示します。
あがg
zZZDfsgsagas
asdfasdf
w235235
12414
agdaga
あああたた
>sort < test.txt
12414
agdaga
asdfasdf
w235235
zZZDfsgsagas
あああたた
あがg
パイプの使用
あるコマンドからの出力を読み取り、別のコマンドの入力に書き込むには「|」演算子を使用します。
たとえば、dirコマンドの出力結果をsortの入力に与えるには以下のようにします。
>dir | sort
2 個のディレクトリ 246,303,686,656 バイトの空き領域
3 個のファイル 116 バイト
C:\dev\bat\redirect のディレクトリ
ドライブ C のボリューム ラベルは OS です
ボリューム シリアル番号は ECD8-AD19 です
2019/10/02 17:18 66 test.txt
2019/10/02 18:07 34 error.txt
2019/10/02 18:10 16 ret.txt
2019/10/02 18:14 <DIR> .
2019/10/02 18:14 <DIR> ..
環境変数
すべてのプロセスは環境変数を使用できます。
環境変数にはユーザ毎のユーザ環境変数と、すべてのユーザ共通のシステム環境変数の2種類があります。
デフォルトの挙動では子プロセスは親プロセスの環境変数を継承します。
GUIでの環境変数の確認と設定
コントロールパネルの「システムとセキュリティ」を選択します。
システムのプロパティが表示されるので「環境変数」を押下します。
ユーザ毎の環境変数とシステムの環境変数が確認と変更が行えます。
コマンドプロンプトでの環境変数
環境変数の確認方法
SETコマンドを実行することで、現在の環境変数を確認できます。
すべての環境変数の一覧を確認するには下記のようなコマンドを実行します。
SET
特定の環境変数の内容を確認するには引数に環境変数名を指定します。
>SET SystemDrive
SystemDrive=C:
環境変数の設定方法
現在のプロセス中での環境変数を設定するにはSETコマンドに変数名と値を指定することで可能です。
SET test=ABCDE
もしコマンドプロンプト中の特殊文字「<、>、| 、&、^」を使用する場合はエスケープ文字である^を使用するか引用符で囲んで文字列として扱います
>set test=a^&n
>set test
test=a&n
>set test="a&n"
>set test
test="a&n"
環境変数の削除
設定した環境変数を削除するには以下のように環境変数だけ入力して値を空にします。
set test=
ユーザに環境変数を設定してもらう
ユーザに環境変数を入力させたい場合は以下のように/pオプションを使用します。
set /p test=
上記のコマンドを入力するとユーザの入力待ちとなり、入力した文字がtest環境変数の値として登録されます。
式を使用して環境変数を設定する
/aオプションを使用することで式を利用して環境変数を設定することが可能です。
>set /a test=10+1
11
数値が使用できますが、これは10進数ばかりでなく、16進数と8進数の使用が可能です。
負の数は使用可能ですが、小数点を使用することはできません。
>set /a test=0x10+1
17
>set /a test=010+1
9
また四則演算、論理演算、ビットシフト等がサポートされています。
>REM 足し算
>set /a test=1+2
3
>REM 引き算
>set /a test=1-2
-1
>REM 割り算
>set /a test=9/3
3
>REM 掛け算
>set /a test=3*2
6
>REM 剰余の例
>set /a test=9%4
1
>REM インクリメントの例
>set /a test=1
1
>set /a test+=1
2
>REM ビット演算の例
>REM 論理積
>set /a test="0x10&0x11"
16
>REM 論理和
>set /a test="0x10|0x11"
17
>REM 排他的論理和
>set /a test="0x10^0x11"
1
>REM ビットシフト
>set /a test="0x10>>1"
8
>set /a test="0x10<<1"
32
環境変数の有効範囲
子プロセスへの環境変数の継承
startコマンドでバッチファイルを呼び出し元プロセスの子プロセスとして実行した場合、実行された子プロセスには親プロセスの環境変数を引き継ぎます。
これは以下のようなコマンドで確認できます。
@echo off
set ver1=testver
set ver1
start /wait cmd /d /c sub0.bat
@echo off
echo sub... %ver1%
pause
呼び出し元のバッチを実行すると、新しいコマンドプロンプトが開いて下記の内容が表示されます。
sub1... testver
つまり、呼び出し元の親プロセスで指定した環境変数が子プロセスに反映されていることが確認できます。
cmdコマンドでのバッチ実行時の環境変数の検証
cmdコマンドでバッチファイルを呼び出した場合、呼び出し先の環境変数は呼び出し元のものが引き継がれますが、呼び出し先の環境変数は呼び出し元には反映されません。
これは以下のようなコマンドで確認できます。
@echo off
set ver1=testver
set ver1
echo begin
cmd /d /c sub.bat
echo end
set ver1
@echo off
echo sub1... %ver1%
set ver1=subver
echo sub2... %ver1%
これの結果は以下のようになります。
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
呼びだし元で設定した環境変数は呼び出し先に反映されることが確認できます。
逆に呼び出し先で設定した環境変数は呼び出し元には反映されていないことが確認できます。
callコマンドを使用した場合の環境変数の継承
callコマンドでバッチファイルを実行した場合、呼び出し元で設定した環境変数は呼び出し先でも反映されます。
これは以下のようなコマンドで確認できます。
@echo off
set ver1=testver
set ver1
echo begin
call sub.bat
echo end
set ver1
呼び出し先はcmdコマンドでのバッチ実行時の環境変数の検証で使用したものと同じになります。
これの実行結果は以下のようになります。
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
呼び出し元が設定した環境変数が呼び出し先に反映される事が確認できます。
また呼び出し先で設定した環境変数が呼び出し元に反映されることが確認できます。
環境変数の反映を制限する
setlocalコマンドを実行することで、バッチファイルの終了時に環境変数の内容を前の状態に戻すことが可能です。
この挙動を確認するには以下を試してみてください。
@echo off
set ver1=testver
set ver1
echo begin
call sublocal.bat
echo end
set ver1
@echo off
setlocal
echo sub1... %ver1%
set ver1=subver
echo sub2... %ver1%
これの実行結果は以下のようになります。
ver1=testver
begin
sub1... testver
sub2... subver
end
ver1=testver
setlocalコマンドがない場合は呼び出し元の環境変数が変更されていましたが、setlocalコマンドを実行することで呼び出し元の環境変数が呼び出し先の変更の影響を受けないことを確認できます。
setlocalコマンドを実行後に変更された環境変数はendlocalコマンドで戻すことが可能です。
endlocalコマンドの挙動を確認するには下記を実行してみてください。
@echo off
set ver1=testver
set ver1
setlocal
set ver1=testlocal
set ver1
endlocal
set ver1
この結果は以下のようになります。
ver1=testver
ver1=testlocal
ver1=testver
endlocalコマンド実行後に環境変数の内容が戻ることが確認できます。
endlocalコマンドはバッチファイルの外では有効ではありません。
また、バッチファイルの最後に暗黙的なendlocalコマンドが実行されます。
恒久的な環境変数の設定方法
前述のSETコマンドで設定した環境変数はプロセスを再起動すると再使用できません。
環境変数を恒久的に登録する場合は、SETXコマンドを使用します。
ユーザ環境変数を登録するには以下のようにコマンドを実行します。
setx test testvalue
システム環境変数を登録するには/mオプションを使用します。管理者権限のコマンドプロンプトで下記を実行してください。
setx test testvalue /m
なお、SETXコマンドで追加したユーザ環境変数、システム環境変数はコマンドプロンプトを再起動した場合に反映されます。
また、SETXコマンドで環境変数を削除することはできません。
以下のようなコマンドで削除できるという非公式な言説もあります。
setx MYVAR ""
実際のシステム設定の環境変数情報からは削除されていませんし、公式のドキュメントで消せないと明言しているので、やめましょう。
You cannot use the setx command to remove values that have been added to the local or system environments.
リモートコンピュータの環境変数の設定
setxコマンドはリモートコンピュータ上の環境変数も変更可能です。
これを使用するにはリモートコンピュータ上の「Remote Registry」サービスを有効にする必要があります。
/sオプションでコンピュータ名、/uオプションでユーザ名、/pオプションでパスワードを指定することでリモートコンピュータの環境変数を変更できます。
setx /s IEWIN7 /u IEUser /p Passw0rd! test testvalue
変更された環境変数はログインをし直すことで有効になります。
なお、「Remote Registry」サービスが起動していない場合、以下のエラーが発生します。
エラー: 指定された操作を完了できませんでした。
環境変数の展開方法
環境変数名を%で囲うことで変数の値が展開されます。
たとえばechoコマンドを使用して、環境変数の値を展開して表示することが可能です。
>echo %SystemDrive%
C:
なお、環境変数は大文字、小文字を区別しないため以下のような記載をしても同じ値が取得できます。
>echo %SYSTEMDRIVE%
C:
なお、この項目についての公式情報は「help set」で確認できます。
環境変数を置換して展開
環境変数の特定の文字を置換して展開することが可能です。
その場合の構文は以下のようになります。
%環境変数:置換前=置換後%
たとえば環境変数PATHの「c:\」を「d:\」に変換するには以下のようにします。
echo %PATH:c:\=d:\%
また置換前の最初の一文字アスタリスクを使用することが可能です。
この場合の挙動は最初に見つけた文字だけが置換されます。実例を以下で紹介します。
>set test=ABCDEFG_ABCDEFG_ABCDEFG
>REM *を使用しない場合、すべての文字が置換されます。
>echo %test:CD=__%
AB__EFG_AB__EFG_AB__EFG
>REM *を使用した場合、発見した最初の文字のみ置換されます。
>echo %test:*CD=cd%
cdEFG_ABCDEFG_ABCDEFG
なお、置換後の文字を空文字とすることで、特定の文字を除去する用途にも使用できます。
環境変数の一部のみ展開
>set test=ABCDEFG_ABCDEFG_ABCDEFG
>REM 6文字目から取得する
>echo %test:~5%
FG_ABCDEFG_ABCDEFG
>REM 6文字目から2文字取得する
>echo %test:~5,2%
FG
>REM 最期の5文字を取得する
>echo %test:~-5%
CDEFG
>REM 最期の5文字を除いて取得する
>echo %test:~0,-5%
ABCDEFG_ABCDEFG_AB
動的な環境変数
SET によって表示される変数の一覧には表示されない動的な環境変数が存在します。
以下の環境変数は実行時に動的に展開されます。
変数名 | 説明 |
---|---|
%CD% | 現在のディレクトリ文字列に展開します。 |
%DATE% | DATEコマンドと同じフォーマットで現在の日付に展開します。 |
%TIME% | TIMEコマンドと同じフォーマットで現在の時刻に展開します。 |
%RANDOM% | 0 から 32767 の間の任意の 10 進数に展開します。 |
%ERRORLEVEL% | 現在の ERRORLEVEL の値に展開します。 |
%CMDEXTVERSION% | 現在のコマンド プロセッサ拡張機能のバージョン番号に展開します。たとえば「cmd /k xxxx.bat」で起動したコマンドプロンプトでこの環境変数を展開した場合、「cmd /k xxxx.bat」となります。 |
%CMDCMDLINE% | コマンド プロセッサを起動したオリジナル コマンド ラインに展開します。 |
%HIGHESTNUMANODENUMBER% | このコンピューター上の最大の NUMA ノード番号に展開します。 |
バッチファイルにおける環境変数
バッチファイルの引数は%1~%9で取得できます。
すべてのパラメータを取得するには「%*」を使用します。
%0を指定した場合はバッチファイル名が取得できます。
以下で、その実行例を確認します。
@echo off
echo %*
echo %0
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
>param1.bat p1 p2 p3 p4 p5 p6 p7 p8 p9
p1 p2 p3 p4 p5 p6 p7 p8 p9
param1.bat
p1
p2
p3
p4
p5
p6
p7
p8
p9
10個以上のパラメータを使用する方法
%には0~9しか指定できません。
10以上のパラメータを使用する場合はshiftコマンドを使用します。
shiftのパラメータとして/2を与えると2番目の引数から右にシフトしていきます。
この実行例は下記のようになります。
@echo off
shift /2
echo %*
echo %0
echo %1
echo %2
echo %3
echo %4
echo %5
echo %6
echo %7
echo %8
echo %9
>param2.bat p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12
p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12
param2.bat
p1
p3
p4
p5
p6
p7
p8
p9
p10
バッチファイルのパラメータで修飾
バッチファイルのパラメータは以下の修飾を行うことが可能です。
バッチパラメータ | 説明 |
---|---|
%~1 | %1を展開し、周囲の引用符("")を削除します。たとえばパラメータに"abc"を与えた場合、abcに変換されます。 |
%~f1 | %1を完全修飾パスに展開します。たとえば相対パスを指定した場合に絶対パスに変換されます |
%~d1 | %1をドライブ文字のみに展開します。 |
%~p1 | %1をパスのみに展開します。 |
%~n1 | %1をファイル名のみに展開します。 |
%~x1 | %1をファイル名拡張子のみに展開します。 |
%~s1 | %1をショートネームのみを含む完全修飾パスに展開します。 |
%~a1 | %1に存在するファイルを指定した場合、そのファイル属性に展開します。 |
%~t1 | %1に存在するファイルを指定した場合、ファイルの更新日時刻に展開します。 |
%~z1 | %1に存在するファイルを指定した場合、ファイルのサイズに展開します。 |
%~$PATH:1 | PATH環境変数にリストされているディレクトリを検索し、%1で指定したファイルを最初に見つけたディレクトリのフルパスに展開します。環境変数名が定義されていないか、検索でファイルが見つからない場合、この修飾子は空の文字列に展開されます。 |
これらの修飾子は組み合わせて使用できます。
たとえば「%~dp0」と記載した場合、バッチファイルの親ディレクトリに展開できます。
動的環境変数を上書きするのは避けてください。
たとえば、以下のように環境変数のERRORLEVELを書き換えても実際の最後に実行したコマンドのエラーコードを書き換えることはできませんし、環境変数を上書きすることで不整合が生じます。
rem this next command sets the error level to zero
CMD /C EXIT 0
set ERRORLEVEL=1
if ERRORLEVEL 1 echo Does this print?
ERRORLEVEL is not %ERRORLEVEL%より
もしERRORLEVELをクリアしたい場合は任意の成功するコマンドを実行する必要があります。
例:
>cmd /c exit /b 0
>ver >nul
遅延環境変数の展開
環境変数は実行時には展開されません。
たとえば以下のバッチファイルを実行したとします。
@echo off
set VAR=before
if "%VAR%" == "before" (
echo if1.....
set VAR=after
if "%VAR%" == "after" echo If 2...
echo %VAR%
)
このバッチファイルの意図としては2つのIF文が共に真になる意図ですが、実際の結果は以下のようになります。
>tien.bat
if1.....
before
1つ目のIFの内での環境変数の設定した内容が反映されていないことがわかります。
実行時に環境変数を展開するためには感嘆符(!)を使用して遅延環境変数を使用する必要があります。
@echo off
set VAR=before
if "%VAR%" == "before" (
echo if1.....
set VAR=after
if "!VAR!" == "after" echo If 2...
echo !VAR!
)
既定の挙動では遅延環境変数は展開されません。
これを有効にするには2種類の方法があります。
cmd実行時に/vオプションを利用する
cmdマンド実行時に/vオプションを使用することで遅延環境変数を展開可能です。
>cmd /v:on /c tien2.bat
if1.....
If 2...
after
setlocalでENABLEDELAYEDEXPANSIONを指定する
setlocalコマンドにenabledelayedexpansionを指定することで遅延変数の展開が可能になります。
この設定はcmdのパラメータより優先されます。
@echo off
SETLOCAL ENABLEDELAYEDEXPANSION
set VAR=before
if "%VAR%" == "before" (
echo if1.....
set VAR=after
if "!VAR!" == "after" echo If 2...
echo !VAR!
)
このバッチファイルの実行結果は下記のようになります。
>tien3.bat
if1.....
If 2...
after
分岐
IFコマンドを使用することで分岐を記述できます。
ERRORLEVELの分岐
「IF ERRORLEVEL 番号」と記載することで最後のプログラムの実行で指定された番号以上の終了コードが返されたときに、条件が真になるように指定します。
>cmd /c exit 1
>IF ERRORLEVEL 1 (echo NG) ELSE (echo OK)
NG
>cmd /c exit 0
>IF ERRORLEVEL 1 (echo NG) ELSE (echo OK)
OK
ERRORLEVELの分岐として環境変数のERRORLEVELを使用することができます。
この場合は以下のいずれかの演算子を指定する必要があります。
- EQU - 等しい
- NEQ - 等しくない
- LSS - より小さい
- LEQ - 以下
- GTR - より大きい
- GEQ - 以上
>cmd /c exit 1
>IF %ERRORLEVEL% equ 0 (echo OK) ELSE (echo NG)
NG
>cmd /c exit 0
>IF %ERRORLEVEL% equ 0 (echo OK) ELSE (echo NG)
OK
ファイルの存在チェック
「IF EXIST ファイル名」と記載することでファイルの存在をチェックすることができます。
>IF EXIST 存在するファイル.txt (echo 真) ELSE (echo 偽)
真
>IF NOT EXIST 存在するファイル.txt (echo 真) ELSE (echo 偽)
偽
>IF EXIST 存在しない.txt (echo 真) ELSE (echo 偽)
偽
>IF NOT EXIST 存在しない.txt (echo 真) ELSE (echo 偽)
真
環境変数の存在チェック
「IF DEFINED 環境変数名」と記載することで環境変数の存在をチェックすることができます。
>set test=
>if DEFINED test (echo 真) ELSE (echo 偽)
偽
>if NOT DEFINED test (echo 真) ELSE (echo 偽)
真
>set test=abc
>if DEFINED test (echo 真) ELSE (echo 偽)
真
>if NOT DEFINED test (echo 真) ELSE (echo 偽)
偽
文字列の比較
==演算子を使用して文字列の比較が可能です。
既定では大文字小文字を区別しますが、/iオプションを使用することで大文字小文字を区別しないで比較をします。
>set test=abc
>IF %test% ==abc (echo 真) ELSE (echo 偽)
真
>IF %test% ==ABC (echo 真) ELSE (echo 偽)
偽
>IF /I %test% ==ABC (echo 真) ELSE (echo 偽)
真
以下のいずれかの演算子を使用して比較することも可能です。
- EQU - 等しい
- NEQ - 等しくない
- LSS - より小さい
- LEQ - 以下
- GTR - より大きい
- GEQ - 以上
>set test=abc
>IF %test% equ abc (echo 真) ELSE (echo 偽)
真
>IF %test% equ ABC (echo 真) ELSE (echo 偽)
偽
>IF NOT %test% neq abc (echo 真) ELSE (echo 偽)
真
>IF NOT %test% neq ABC (echo 真) ELSE (echo 偽)
偽
>IF /I %test% equ ABC (echo 真) ELSE (echo 偽)
真
EQUなどの演算子を使用すると数値としても使用することが可能です。
>set num=10
>IF %num% GEQ 9 (echo 真) ELSE (echo 偽)
真
>IF %num% GEQ 10 (echo 真) ELSE (echo 偽)
真
>IF %num% GEQ 11 (echo 真) ELSE (echo 偽)
偽
>IF %num% LEQ 9 (echo 真) ELSE (echo 偽)
偽
>IF %num% LEQ 10 (echo 真) ELSE (echo 偽)
真
>IF %num% LEQ 11 (echo 真) ELSE (echo 偽)
真
繰り返し
forコマンドを使用することで繰り返し処理を記述できます。
セットの繰り返し
for {%%|%}<変数名> in (セット) do コマンド [コマンドライン引数]
in句の後で指定したセットを繰り返すことが可能です。
コマンドラインで実行する場合の例は以下のようになります。
>for %a in (ab,cd,ef,eataeta) do @(echo %a)
ab
cd
ef
eataeta
IN句のセットの書き方は以下のようにも記載できます。
>for %a in (ab;cd;ef;eataeta) do @(echo %a)
>for %a in (ab cd ef eataeta) do @(echo %a)
バッチファイルを使用する場合は以下のようになります。
@echo off
for %%a in (ab,cd,ef,eataeta) do (
echo %%a
)
>dataset.bat
ab
cd
ef
eataeta
ワイルドカードの使用
セットにはワイルドカードを指定してファイルを取得することができます。
バッチファイルで使用する場合、変数には「%%」を指定してください。
>for %a in (*.txt) do @(echo %a)
error.txt
list.txt
result.txt
ret.txt
>for %a in (c:\dev\bat\*) do @(echo %a)
c:\dev\bat\init.bat
c:\dev\bat\initCur.bat
c:\dev\bat\t.bat
c:\dev\bat\test.bat
c:\dev\bat\testchoise.bat
c:\dev\bat\testLs.bat
c:\dev\bat\testLs2.bat
既定ではディレクトリの取得はできません。
ディレクトリの取得
/dオプションを使用するとディレクトリを取得することができます。
バッチファイルで使用する場合、変数には「%%」を指定してください。
>for /d %a in (c:\dev\bat\*) do @(echo %a)
c:\dev\bat\bunki
c:\dev\bat\file
c:\dev\bat\func
c:\dev\bat\redirect
c:\dev\bat\run
c:\dev\bat\test
c:\dev\bat\test2
c:\dev\bat\ver
ファイルを再帰的に取得
/rオプションを使用すると指定したディレクトリを再帰的に探査可能です。
バッチファイルで使用する場合、変数には「%%」を指定してください。
>for /r c:\dev\ %a in (*.txt) do @(echo %a)
c:\dev\akanechan_powerpoint\Slide1_0.txt
c:\dev\akanechan_powerpoint\Slide1_1.txt
c:\dev\akanechan_powerpoint\Slide1_2.txt
c:\dev\bat\bunki\error.txt
c:\dev\bat\bunki\list.txt
c:\dev\bat\bunki\result.txt
c:\dev\bat\bunki\ret.txt
c:\dev\bat\file\1.txt
c:\dev\bat\file\2.txt
変数の展開の修飾子
ループで使用する変数については以下の修飾子が使用できます。
以下の説明は%Iを変数とした場合の修飾子の例になります。
%~I - すべての引用句 (") を削除して、%I を展開します。
%~fI - %I を完全修飾パス名に展開します。
%~dI - %I をドライブ文字だけに展開します。
%~pI - %I をパス名だけに展開します。
%~nI - %I をファイル名だけに展開します。
%~xI - %I をファイル拡張子だけに展開します。
%~sI - 展開されたパスは短い名前だけを含みます。
%~aI - %I をファイルの属性に展開します。
%~tI - %I ファイルの日付/時刻に展開します。
%~zI - %I ファイルのサイズに展開します。
%~$PATH:I - PATH 環境変数に指定されているディレクトリを
検索し、最初に見つかった完全修飾名に %I を
展開します。
環境変数名が定義されていない場合、または検索
してもファイルが見つからなかった場合は、この
修飾子を指定すると空の文字列に展開されます。
使用例は以下のようになります。
>for %I in (*.txt) do @echo %~fI %~dI %~pI %~nI %~xI %~sI %~aI %~tI %~zI
C:\dev\bat\bunki\error.txt C: \dev\bat\bunki\ error .txt C:\dev\bat\bunki\error.txt --a-------- 2019/09/28 16:02 0
C:\dev\bat\bunki\list.txt C: \dev\bat\bunki\ list .txt C:\dev\bat\bunki\list.txt --a-------- 2019/09/28 02:50 81
C:\dev\bat\bunki\result.txt C: \dev\bat\bunki\ result .txt C:\dev\bat\bunki\result.txt --a-------- 2019/09/28 03:59 17
C:\dev\bat\bunki\ret.txt C: \dev\bat\bunki\ ret .txt C:\dev\bat\bunki\ret.txt --a-------- 2019/09/28 16:49 3
C:\dev\bat\bunki\te st.txt C: \dev\bat\bunki\ te st .txt C:\dev\bat\bunki\te st.txt --a-------- 2019/10/02 21:38 92
C:\dev\bat\bunki\test.txt C: \dev\bat\bunki\ test .txt C:\dev\bat\bunki\test.txt --a-------- 2019/10/02 21:38 92
値の範囲を繰り返す
/Lオプションを使用することで値の範囲を指定することができます。
書式としては以下のようになります。
for /l {%%|%}<変数名> in (開始値,増分,終了値) do コマンド [コマンドライン引数]
ループカウンタに使用する変数はコマンドラインで実行する場合は「%変数名」となり、バッチファイル中で使用する場合は「%%変数名」となります。
in句の後にはループカウンタの開始値、増分、終了値の順番で指定します。
コマンドプロンプトで実行する場合の例は以下のようになります。
>for /L %a in (0, 2, 9) do @(echo %a)
0
2
4
6
8
バッチファイルの場合は以下のようになります。
@echo off
for /L %%a in (0, 2, 9) do (
echo %%a
)
>loop.bat
0
2
4
6
8
ファイルの解析
/Fオプションを使用することでファイルの内容を1行づつ解析できます。
たとえば以下のようなファイルが存在するとします。
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
これを一行づつ処理するには以下のようにします。
>FOR /F %a in (test.txt) do @echo %a
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
ああああ,いいい,ううう
一行づつechoコマンドが実行されます。
ただし、;で開始している行はコメント行として処理されてループの対象となりません。
もしバッチファイル内で使用するには%aを%%aと置き換えます。
/Fオプションの後に以下のキーワードを使用することが可能です。
- eol
- skip
- usebackq
- delims
- tokens
eolキーワード
eolで指定した1文字がコメント行として解釈されます。
eolを指定しない場合は「;」で開始される行がコメント行として処理されます。
>FOR /F "eol=1" %a in (test.txt) do @echo %a
2345,6789,abcd
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
skipキーワード
skip行で指定した行数を飛ばしてループの対象とします。
たとえば以下の場合、先頭の2行をスキップして行をループします。
>FOR /F "eol=# skip=2" %a in (test.txt) do @echo %a
3456,789a,bcde
;aaa,bbb,cccコメント
ああああ,いいい,ううう
usebackqキーワード
セットに指定するファイル名に二重引用符で囲むことを許可します。
これにより空白のファイル名を指定できます。
>FOR /F "usebackq" %a in ("te st.txt") do @echo %a
1234,5678,9abc
2345,6789,abcd
3456,789a,bcde
ああああ,いいい,ううう
delims、tokensキーワード
delimsキーワードは区切り文字を指定できます。デフォルトはスペースまたはTabになります。
tokensキーワードはどのトークンをループにわたすかを指定できます。
たとえば「,」区切って1つ目と3つ目を表示するには以下のように指定します。
>FOR /F "delims=, tokens=1,3" %a in (test.txt) do @echo %a %b
1234 9abc
2345 abcd
3456 bcde
ああああ ううう
たとえば「,」区切って2つ目~3つ目を表示するには以下のように指定します。
>FOR /F "delims=, tokens=2-3" %a in (test.txt) do @echo %a %b
5678 9abc
6789 abcd
789a bcde
いいい ううう
tokensに*を指定することで、解析される最後のトークンの後の行に残っているテキストを受け取ります。
>FOR /F "delims=, tokens=1,*" %a in (test.txt) do @echo %a %b
1234 5678,9abc
2345 6789,abcd
3456 789a,bcde
ああああ いいい,ううう
コンソールの操作
コンソールのクリア
clsコマンドを使用することでコンソールの内容をクリアできます。
タイトルの変更
titleコマンドを使用することでコマンドプロンプトのタイトルを変更できます。
title タイトルの変更
ポーズコマンド
pauseコマンドを使用することでキーボードの入力待ちが行えます。
>pause
続行するには何かキーを押してください . . .
ユーザ入力
choiceコマンドを使用することでユーザ入力を行えます。
ユーザが選択した結果は%ERRORLEVEL%に格納されます。
>choice /m 選択してください
選択してください [Y,N]?Y
>echo %ERRORLEVEL%
1
>choice /m 選択してください
選択してください [Y,N]?N
>echo %ERRORLEVEL%
2
既定ではY,Nの選択になりますが、/cオプションを使用することで選択項目をカスタマイズできます。
>choice /c ync1234567890 /m 選択してください
選択してください [Y,N,C,1,2,3,4,5,6,7,8,9,0]?2
>echo %ERRORLEVEL%
5
ファイル操作
カレントディレクトリの設定
カレントディレクトリの移動には2種類の方法があります。
cdまたはchdirによるカレントディレクトリの変更
cdコマンドまたはchdirコマンドでカレントディレクトリを変更します。
ドライブを変更する場合は/dオプションを使用してください。
cd c:\
chdir c:\dev
chdir /d e:\
cd /d c:\
スタックを使用したカレントディレクトリの変更
pushdコマンドとpopdコマンドを使用することでスタックを使用してカレントディレクトリを変更できます。
これを呼び出し先のバッチファイルで使用することで呼び出し先で変更したカレントディレクトリを呼び出し元のカレントディレクトリに戻すことが可能になります。
以下にpushdコマンドと[popdコマンド]の実行例を記述します。
c:\>pushd c:\dev
c:\dev>pushd c:\dev\bat
c:\dev\bat>popd
c:\dev>popd
pushdで変更したディレクトリがpopdで元に戻ることが確認できると思います。
空ファイルの作成
copyコマンドを使用してnulでファイルを作成すると空ファイルが作成できます。
すでにあるファイルを空にする場合は/yオプションを使用して強制的に上書きします。
copy nul test.txt
copy /y nul test.txt
ディレクトリの作成
mdコマンドまたはmkdirコマンドでディレクトリを作成します。
中間ディレクトリがない場合は作成されます。
すでに存在するディレクトリを指定した場合はエラーとなります。
md test\test\test
mkdir test2\test\test
リンクの作成
mklinkコマンドを使用してシンボリックリンク、ハードリンク、ジャンクションが作成可能です。
これらの違いは下記を参照してください。
Windowsのシンボリックリンクとジャンクションとハードリンクの違い
https://www.atmarkit.co.jp/ait/articles/1306/07/news111.html
シンボリックリンクの作成
ディレクトリのシンボリックリンクを作成する場合は/Dオプションを使用してください。
またディレクトリのシンボリックリンクを作成する場合は管理者権限で実行する必要があります。
mklink slink_a.txt c:\dev\ps\file\link\a.txt
mklink sdir c:\dev\ps\file\link\sub2 /D
ハードリンクの作成
ハードリンクを作成するには/hオプションを使用してください。
mklink /H hardlink_a.txt c:\dev\ps\file\link\a.txt
ジャンクションの作成
/jオプションを使用することでジャンクションを作成できます。
mklink /j junction_dir c:\dev\ps\file\link\sub1
ファイルとディレクトリの列挙
一覧表示
dirコマンドを使用するとサブディレクトリの一覧を表示します。
ディレクトリを指定する場合、*または?のワイルドカードが使用できます。*は任意の文字列、?は任意の一文字以下をあらわします。
たとえばディレクトリは以下に以下のファイルが存在したとします。
- abcde.txt
- abcd.txt
- abc.txt
- ab.txt
- a.txt
- a.text
- .txt
「*.txt」を指定して検索した場合以下のファイルが列挙されます。
- abcde.txt
- abcd.txt
- abc.txt
- ab.txt
- a.txt
「????.txt」を指定した場合以下のファイルが列挙されます。
- abcd.txt
- abc.txt
- ab.txt
- a.txt
/aオプションを使用することで隠しファイルやシステムファイルも表示可能になります。
/sオプションを使用することでサブディレクトリの内容を表示します。
コマンドの使用例は以下のようになります。
REM 拡張子がtxtのファイルを列挙
dir C:\dev\ps\file\link\*.txt
REM 拡張子がtxtのファイルを列挙
dir C:\dev\ps\file\link\????.txt
REM 隠しファイル含めて列挙
dir C:\dev\ps\file\link\sub1 /a
REM サブディレクトリを列挙
dir C:\dev\ps\file\link\ /s
ツリー構造での表示
treeコマンドを使用することでディレクトリ構造をツリー構造で表示します。
/fオプションを使用することでファイルも表示可能ですが、隠しファイルを表示することはできません。
>tree /f c:\dev\bat\file
ディレクトリー パスの一覧: ボリューム OS
ボリューム シリアル番号は ECD8-AD19 です
C:\DEV\BAT\FILE
│ .txt
│ a.text
│ a.txt
│ ab.txt
│ abc.txt
│ abcd.txt
│ abcde.txt
│
└─sub1
test.txt
test2.txt
ファイルの検索
whereコマンドを使用することで指定したファイルのパスを検索できます。
一致するファイルの検索パターンにはワイルドカード(*と?)が使用できます。ワイルドカードの挙動はdirコマンドで説明した挙動と同じです。ディレクトリを指定するか、環境変数を指定することが可能ですが、いずれも指定せずに検索した場合はカレントディレクトリとPATH環境変数で指定したディレクトリを検索します。
/Rオプションと組み合わせてディレクトリを指定することで特定のディレクトリ以下のサブディレクトリをすべて検索します。
隠しファイルが存在する場合、それも検索対象となります。
REMカレントディレクトリと環境変数PATH以下でtxt拡張子のファイルを検索する
where *.txt
REM環境変数Publicのディレクトリのファイルを検索する
where $PUBLIC:*.*
REM 特定のディレクトリを再帰的に検索して*.txtにマッチするファイルを検索する
where -R C:\dev\ps\file\link\sub1 *.txt
ファイルの削除
ファイルの削除にはdelコマンドを使用します。
削除対象のファイルはワイルドカード(*と?)が使用できます。ワイルドカードの挙動はdirコマンドで説明した挙動と同じです。
ゴミ箱には送らない、取り返しのつかない操作なので十分に注意して使用してください。
REM カレントディレクトリのtxt拡張子を削除する
del *.txt
REM 特定ディレクトリのtxt拡張子を削除する
del c:\dev\bat\*.txt
規定の動作では隠しファイルや読み取り専用ファイルを削除できません。
/fと/aオプションを付与して削除してください。
del /a /f *.txt
/pオプションを使用することで確認メッセージを表示可能になります。
>del /p *.txt
C:\dev\bat\file\ab.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abc.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abcd.txt を削除しますか (Y/N)? n
C:\dev\bat\file\abcde.txt を削除しますか (Y/N)? n
C:\dev\bat\file\test.txt を削除しますか (Y/N)? n
C:\dev\bat\file\test2.txt を削除しますか (Y/N)? n
ディレクトリの削除
ディレクトリの削除にはrmdirコマンドまたはrdコマンドを使用します。ゴミ箱には送らない、取り返しのつかない操作なので十分に注意して使用してください。
/sオプションを指定することでサブディレクトリを含めて削除可能です。この際確認メッセージが表示されますが、確認メッセージを表示しないようにするには/qオプションを使用します。
>rmdir /s sub2
sub2、よろしいですか (Y/N)? y
>rmdir /s /q sub2
削除対象のディレクトリをカレントディレクトリとして使用しているプロセスがある場合以下のようなメッセージが表示されます。
>rmdir /s /q c:\dev\bat\file\sub2
プロセスはファイルにアクセスできません。別のプロセスが使用中です。
ファイルの改名
ファイルまたはディレクトリの改名にはrenコマンドまたはrenameコマンドを使用します。
ファイルの改名にはワイルドカードを使用することが可能です。ワイルドカードの挙動はdirコマンドで説明した挙動と同じです。ただし、隠しファイルは対象となりません。
REM c:\dev\bat\file\sub1ディレクトリをc:\dev\bat\file\sub1_renamedに変更します。
ren c:\dev\bat\file\sub1 sub1_renamed
REM 拡張子txtをdocに変更します。
ren *.txt *.doc
ファイルのコピー
copyコマンドを使用してコピー元のファイルを指定のディレクトリまたはファイルにコピーします。
REM ファイルを指定してコピー
>copy ab.doc z.doc
1 個のファイルをコピーしました。
REM directoryを指定してコピー
>copy *.doc C:\dev\bat\file\sub2
ab.doc
abc.doc
abcd.doc
abcde.doc
test.doc
5 個のファイルをコピーしました。
ディレクトリのコピー
xcopyコマンドを使用してディレクトリのコピーが可能です。
/sオプションでサブディレクトリのコピーも可能です。
/eオプションで空のサブディレクトリもコピーします。
/hオプションで隠しファイルのコピーも行います。デフォルトでは隠しファイルをコピーしません。
/kオプションでコピー元の読み取り専用属性をコピー先に反映させます。デフォルトでは反映されません。
REM 隠しファイルはコピーされない
xcopy c:\dev\bat\file\sub c:\dev\bat\file\target /s /e
REM 隠しファイルはコピーされる
xcopy c:\dev\bat\file\sub c:\dev\bat\file\target /s /e /h
コピーの挙動としては以下のようになります。
target
sub の子要素1
孫要素
sub の子要素2
ファイル/ディレクトリの移動
moveコマンドを使用してファイルまたはディレクトリを移動します。
/yオプションを使用することで移動先がすでに存在する場合に確認メッセージを表示しないで上書きしません。
>move ab.doc xxx.doc
1 個のファイルを移動しました。
>move /y abcd.doc abc.doc
1 個のファイルを移動しました。
>move sub2 sub3
1 個のディレクトリを移動しました。
ファイルの内容表示
typeコマンドまたはmoreコマンドを使用することでファイルの内容を表示します。
typeコマンドは一度にすべて表示します。
moreコマンドは1ページづつ表示されます。
>type sjis.txt
>more sjis.txt
デフォルトのコードページ以外(日本語OSの場合はcp932)のファイルとUNICODE以外のテキストファイルを表示する場合はchcpコマンドを使用します。
REM BOMなしのUTF8を表示します。
>chcp 65001
>type utf8.txt
なお古いバージョンのWindowsだとフォントの都合で表示されません。cp932でフォントをMSゴシックを選択していれば表示される場合もありますが、正直、すべての環境での挙動が安定していないように見えます。
またchcpを使用した場合、moreコマンドを使用すると文字化けします。
SJISやUNICODE以外の文字コードを扱う場合は、PowerShellでも使った方が楽だと思います。
ファイルの連結
typeコマンドを使用するか、copyコマンドを使用します。
たとえば以下のような2ファイルがあるとします。
あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
1.txtの末尾に2.txtを結合するには以下のようにします。
REM 1.txtの末尾に2.txtが追記
type 2.txt >> 1.txt
REM 1.txtの後に2.txtが追記された結果がresult.txtに書き込まれる。
copy /b 1.txt+2.txt result.txt
copyコマンドの/bオプションはバイナリでの連結を意味します。これを付与しない場合、末尾に0x1A(CTRL+Z)が付与されます。
ファイルの属性変更
attribコマンドを使用することでファイルの属性を変更できます。
REM 読み取り専用にする
attrib result.txt +R
REM 読み取り専用を解除
attrib result.txt -R
REM 読み取り専用、隠しファイル、システムファイルとする
attrib result.txt +R +H +S
ファイルの所有者変更
管理者権限でicacls コマンドを使用することでファイルの所有者を変更可能です。
icacls result.txt /setowner NOTE-MAIN\mima
ファイル中の文字検索
findコマンドまたはfindstrコマンドを使用します。
>find "あい" *.txt
---------- 1.TXT
あいうえお
---------- 2.TXT
---------- RESULT.TXT
あいうえお
サブディレクトリも検索する場合はfindstrコマンドの/sオプションを使用します。
>findstr /s "あい" *.txt
1.txt:あいうえお
result.txt:あいうえお
sub\1.txt:あいうえお
ファイルの比較
compコマンド
compコマンドはバイナリでファイルを比較します。
/mオプションを付けない場合、続けてファイルを比較するようなプロンプトを表示します。
ファイルの比較結果が同一の場合、ERRORLEVELは0となります。
ファイルの比較結果が異なる場合、ERRORLEVELは1となります。
構文エラーがある場合、ERRORLEVELは2となります。
REM ファイルが等しい場合はERRORLEVELは0となります。
>comp /m 1.txt 1.txt
1.txt と 1.txt を比較しています...
ファイルに違いはありません
>echo %ERRORLEVEL%
0
REM ファイルサイズが異なる場合
>comp /m 1.txt 4.txt
1.txt と 4.txt を比較しています...
ファイルのサイズが違います。
>echo %ERRORLEVEL%
1
REM ファイルサイズが等しくて内容が異なる場合
>comp /m 1.txt 3.txt
1.txt と 3.txt を比較しています...
OFFSET 11 で比較エラーがあります
ファイル1 = AD
ファイル2 = AF
OFFSET 1B で比較エラーがあります
ファイル1 = B5
ファイル2 = A2
>echo %ERRORLEVEL%
1
fcコマンド
fcコマンドはASCII比較またはバイナリーでの比較が行えます。
ファイルの比較結果が同一の場合、ERRORLEVELは0となります。
ファイルの比較結果が異なる場合、ERRORLEVELは1となります。
構文エラーがある場合、ERRORLEVELは2となります。
/Bオプションを使用することでバイナリの比較を実行します。
/Uオプションを使用することでUNICODEで比較を実行します。
ASCII比較時に/Nオプションを使用することで行番号を表示します。
REM 相違点のあるファイルをASCIIで比較
>fc /N fc1sjis.txt fc2sjis.txt
ファイル fc1sjis.txt と FC2SJIS.TXT を比較しています
***** fc1sjis.txt
4: あいうえお
5: かきくけこ
6: a
***** FC2SJIS.TXT
4: あいうえお
5: かきけっけけこ
6: a
*****
***** fc1sjis.txt
10: 35235235235
11: 3252353efwrwerwrwr
***** FC2SJIS.TXT
10: 35235235235
11: ああああ
12: 3252353efwrwerwrwr
*****
>echo %ERRORLEVEL%
1
REM 相違点のないファイルを比較
>fc /N fc1sjis.txt fc1sjis.txt
ファイル fc1sjis.txt と FC1SJIS.TXT を比較しています
FC: 相違点は検出されませんでした
>echo %ERRORLEVEL%
0
REM バイナリモードで比較を行う
>fc /B 1.txt 3.txt
ファイル 1.txt と 3.TXT を比較しています
00000011: AD AF
0000001B: B5 A2
>echo %ERRORLEVEL%
1
C:\dev\bat\file>fc /B 1.txt 4.txt
ファイル 1.txt と 4.TXT を比較しています
00000010: 82 61
00000011: AD 82
REM 略
00000021: BB 82
FC: 4.TXT は 1.txt より長いファイルです
>echo %ERRORLEVEL%
1
REM UNICODEのファイルを比較する
>fc /N /U fc1unicode.txt fc2unicode.txt
ファイル fc1unicode.txt と FC2UNICODE.TXT を比較しています
***** fc1unicode.txt
4: あいうえお
5: かきくけこ
6: a
***** FC2UNICODE.TXT
4: あいうえお
5: かきけっけけこ
6: a
*****
***** fc1unicode.txt
10: 35235235235
11: 3252353efwrwerwrwr
***** FC2UNICODE.TXT
10: 35235235235
11: ああああ
12: 3252353efwrwerwrwr
*****
レジストリの操作
レジストリの操作はregコマンドを使用しておこないます。
レジストリの詳細は下記を参照してください。
https://qiita.com/mima_ita/items/ff656af8e4b56ed17a53
レジストリの参照
regコマンドのqueryを用いることでレジストリの参照が可能です。
/vオプションを使用することで値を指定してレジストリの内容を表示します。
/sオプションを使用することで再帰的にレジストリキーの内容を表示します。
REM レジストリ―キーの内容を確認する
>reg query HKCU\test\a\b\
HKEY_CURRENT_USER\test\a\b
(既定) REG_SZ
data REG_SZ test2
test REG_EXPAND_SZ %PATH%
REM 特定のレジストリ―キーの値の内容を確認する
>reg query HKCU\test\a\b\ /v test
HKEY_CURRENT_USER\test\a\b
test REG_EXPAND_SZ %PATH%
REM レジストリキーを再帰的に確認する
>reg query HKCU\test\ /s
HKEY_CURRENT_USER\test\a
x REG_SZ abc
HKEY_CURRENT_USER\test\a\b
(既定) REG_SZ
data REG_SZ test2
test REG_EXPAND_SZ %PATH%
リモートコンピュータ側のRemote Registryサービスを起動することでコンピュータ名を指定してレジストリの参照が行えます。
>reg query \\IEWin7\HKLM\SOFTWARE
レジストリの登録
regコマンドのaddを用いることでレジストリの登録が可能です。
レジストリキーを登録する場合は以下を実行します。
reg add HKCU\test\a\b
指定したキーの途中が存在しない場合でもエラーとならず作成されます。
またすでにキーが存在する場合は下記の確認メッセージが表示されます。
値 は存在します。上書きしますか? (Yes/No)
レジストリの値を追加するには以下のようになります。
reg add HKCU\test\a\b /v data /t REG_SZ /d test2
指定したキーが存在しない場合でもエラーとならず作成されます。
またすでにキーが存在する場合は確認メッセージが表示されます。
リモートコンピュータ側のRemote Registryサービスを起動することでコンピュータ名を指定してレジストリの追加が行えます。
>reg add \\IEWin7\HKLM\SOFTWARE\test\a\b /v data /t REG_SZ /d test2
レジストリのエクスポート
regコマンドのexportを用いることでレジストリの内容をファイルにエクスポートすることが可能です。
reg export HKCU\test\ export.reg
レジストリのインポート
regコマンドのimportを用いることでファイルの内容をレジストリにインポートすることが可能です。
reg import export.reg
スリープ処理
コマンドプロンプトやバッチファイルでスリープ処理を入れる方法は色々あります。
- timeoutコマンド
- pingコマンド
- powershellでスリープ
timeoutコマンド
timeoutコマンドを使用することでスリープ処理がおこなえます。
5秒待機する場合は以下のように記載します。
timeout /t 5 /nobreak > nul
なお、timeoutコマンドを以下のように記載することでpauseコマンドかわりにしようできます。
>timeout /t -1
続行するには何かキーを押してください ...
pingコマンド
pingコマンドのタイムアウトを使用する方法もよくつかわれます。
timeoutと違いミリ秒で指定できます。
5秒待機する場合は以下のように存在しないホストに対してPingを実行します。
ping 111.111.111.111 -n 1 -w 5000 > nul
powershellでスリープ
PowerShellが入っている環境ではPowerShellのStart-Sleepコマンドを使用するといいでしょう。
5秒待機する場合は以下のように記載します。
powershell -command "Start-Sleep 5.0"
powershell -command "Start-Sleep -Milliseconds 5000"
コンピュータの操作
OSのバージョンを表示する
verコマンドでオペレーションシステムのバージョンが取得できます。
>ver
Microsoft Windows [Version 10.0.17134.1006]
ホスト名を表示する
hostコマンドでホスト名を表示します。
>hostname
NOTE-MAIN
ネットワーク構成の情報を表示
[ipconfigコマンド]を使用することで現在のすべてのTCP / IPネットワーク構成値を表示できます。
>ipconfig
Windows IP 構成
イーサネット アダプター VirtualBox Host-Only Network:
接続固有の DNS サフィックス . . . . .:
リンクローカル IPv6 アドレス. . . . .: fe80REMdd98:fe1c:2a3c:ff4d%21
IPv4 アドレス . . . . . . . . . . . .: 192.168.56.1
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .:
システム情報
systeminfoコマンドを使用することでローカルコンピュータまたはリモートコンピュータのシステム情報を表示します。
REM ローカルコンピュータのシステム情報
>systeminfo
REM リモートコンピュータのシステム情報を表示する
>systeminfo /S IEWin7 /U IEUser /P Passw0rd!
ホスト名: IEWIN7
OS 名: Microsoft Windows 7 Enterprise
OS バージョン: 6.1.7601 Service Pack 1 ビルド 7601
OS 製造元: Microsoft Corporation
OS 構成: スタンドアロン ワークステーション
OS ビルドの種類: Multiprocessor Free
登録されている所有者:
登録されている組織: Microsoft
プロダクト ID: 00392-972-8000024-85432
最初のインストール日付: 2018/03/06, 19:59:43
システム起動時間: 2019/10/01, 16:02:36
システム製造元: VMware, Inc.
システム モデル: VMware Virtual Platform
システムの種類: x64-based PC
プロセッサ: 1 プロセッサインストール済みです。
[01]: Intel64 Family 6 Model 142 Stepping 9 GenuineIntel ~2712 Mhz
BIOS バージョン: Phoenix Technologies LTD 6.00, 2019/07/29
Windows ディレクトリ: C:\Windows
システム ディレクトリ: C:\Windows\system32
起動デバイス: \Device\HarddiskVolume1
システム ロケール: ja;日本語
入力ロケール: en-us;英語 (米国)
タイム ゾーン: (UTC-08:00) 太平洋標準時 (米国およびカナダ)
物理メモリの合計: 2,047 MB
使用できる物理メモリ: 1,609 MB
仮想メモリ: 最大サイズ: 4,095 MB
仮想メモリ: 使用可能: 3,659 MB
仮想メモリ: 使用中: 436 MB
ページ ファイルの場所: C:\pagefile.sys
ドメイン: WORKGROUP
ログオン サーバー: N/A
ホットフィックス: 219 ホットフィックスがインストールされています。
[01]: KB2849697
[02]: KB2849696
~~~~~~略~~~~~~~~~~
[218]: KB982018
[219]: KB4516065
ネットワーク カード: 1 NIC(s) インストール済みです。
[01]: Intel(R) PRO/1000 MT Network Connection
接続名: Local Area Connection 2
DHCP が有効: はい
DHCP サーバー: 192.168.80.254
IP アドレス
[01]: 192.168.80.128
[02]: fe80REM151b:4382:b14b:d9e8
Hyper-V の要件: VM モニター モード拡張機能: いいえ
ファームウェアで仮想化が有効になっています: いいえ
第 2 レベルのアドレス変換: いいえ
データ実行防止が使用できます: はい
タスクの一覧を表示する
tasklistコマンドを使用することでタスクの一覧を表示できます。
REM ローカルコンピュータのタスク一覧を表示
>tasklist
REM リモートコンピュータのタスク一覧を表示
>tasklist /S IEWin7 /U IEUser /P Passw0rd!
イメージ名 PID セッション名 セッション# メモリ使用量
========================= ======== ================ =========== ============
System Idle Process 0 0 24 K
System 4 0 960 K
smss.exe 256 0 1,024 K
csrss.exe 324 0 4,844 K
略
/fiオプションを使用することでフィルタを使用できます。
たとえばイメージ名がchrome.exeと一致するタスクの一覧を取得するには以下のようになります。
>tasklist /fi "IMAGENAME eq chrome.exe"
フィルタ名 | 有効なオペレータ | 有効な値 |
---|---|---|
STATUS | eq, ne | RUNNING |
IMAGENAME | eq, ne | イメージ名 |
PID | eq, ne, gt, lt, ge, le | PID value |
SESSION | eq, ne, gt, lt, ge, le | Session number |
SESSIONNAME | eq, ne | Session名 |
CPUTIME | eq, ne, gt, lt, ge, le | CPUタイムを「HH:MM:SS」形式で指定します。MMとSSは0 ~ 59、 HH は正の数値です |
MEMUSAGE | eq, ne, gt, lt, ge, le | メモリの使用量(KB) |
USERNAME | eq, ne | Any valid user name |
SERVICES | eq, ne | Service name |
WINDOWTITLE | eq, ne | Windowタイトル |
MODULES | eq, ne | DLL名を指定してDLLを使用しているタスクの一覧を取得します |
タスクを終了する
taskkillコマンドを使用してプロセスIDまたはイメージ名を指定してタスクを終了できます。
REM プロセスIDを指定して終了する
>taskkill /pid 26220 /pid 30392
成功: PID 26220 のプロセスに強制終了のシグナルを送信しました。
成功: PID 30392 のプロセスに強制終了のシグナルを送信しました。
REM イメージ名を指定して終了する
>taskkill /im notepad.exe
成功: プロセス "notepad.exe" (PID 30396) に強制終了のシグナルを送信しました。
成功: プロセス "notepad.exe" (PID 36840) に強制終了のシグナルを送信しました。
REM イメージ名にワイルドカードを指定して終了する
>taskkill ./im note*
成功: プロセス "notepad2.exe" (PID 31492) に強制終了のシグナルを送信しました。
成功: プロセス "notepad.exe" (PID 1140) に強制終了のシグナルを送信しました。
REM リモートコンピュータのタスクを終了する
>taskkill /s IEWin7 /u IEUser /p Passw0rd! /im notepad.exe
成功: プロセス "notepad.exe" (PID 996) は強制終了されました。
またtasklistコマンドと同様に/fiオプションを使用してフィルタをかけて一括でタスクを終了できます。
>taskkill /fi "IMAGENAME eq notepad.exe"
シャットダウン、再起動、ログオフ
shutdownコマンドでシャットダウン、再起動、ログオフが可能です。
REM ログオフをする
shutdown /l
REM ただちに再起動をする
shutdown /r /t 0
REM ただちにシャットダウンする
shutdown /s /t 0
まとめ
以上、簡単にコマンドプロンプトの操作やバッチファイルの使用例を公式ドキュメントベースでまとめました。
意外と大きな会社がやっているサイトのホームページでも、コマンドプロンプトやバッチファイルの使い方についての記事で参考文献に公式ドキュメントのリンクはっていない場合があるので、レビュアーが公式ドキュメント厨のときには攻略に役に立つと思います。
また、現在はPowerShellを使った方が楽だと思いますが、コマンドプロンプトでの操作やバッチファイルは自動化の基本となるものなので、軽く覚えておいた方が便利だと思います。
おまけ:「PowerShellが実行できないよ!」
どういう状況かをいっているか認識があっているかわかりませんが、初期状態でスクリプトが実行ポリシーの問題で実行できないといっていると仮定します。
上記にあるようにやり方としては管理者権限をもって実行ポリシーを変更するか、以下のようなコマンドでスクリプトを実行します。これには管理者権限は不要です。
powershell -ExecutionPolicy RemoteSigned .\test.ps1