CMD(windowsコマンドプロンプト)メモ

Feb2015 coskx

よく使うけれど,毎回調べなおしている項目

1.cmdファイル起動パラメタ
1.1 
cmdファイル起動パラメタを利用する
>xxxx.cmd par1 param2 param3
の形でxxxx.cmdを起動すると,cmd内部では3つのパラメタが%1 %2 %3で参照される

echo3.cmdを次のように作る
@echo off
echo %0
echo %1
echo %2
echo %3
この時
echo3.cmd tokyo osaka kyoto
と起動すると
echo3.cmd
tokyo
osaka
kyoto
が表示される。
もし,echo3.cmdのアイコンに何かのファイルまたはフォルダのアイコンをドロップすると
%1のところにドロップされたファイルあるいはフォルダの名前がフルパスで表示される。

1.2.%の使い方
cmdファイル内で%1を使った記述を置き,ファイルのアイコンをドロップする
このとき
%1 ファイル名がフルパス
%~d1 ファイルのドライブ名 例えばc:
%~p1
ファイルのパス名 例えばc:\xxx\yyy\zzz\
%~nx1
ファイル名 例えばmyfile,txt
%~n1
ファイルのプライマリ名 例えばmyfile
%~x1
ファイルの拡張子 例えば.txt
よく使う例1 cmd自分自身のあるフォルダをカレントにする
%~d0
cd %~p0
よく使う例2 ドロップされたファイルのあるフォルダをカレントにする
%~d1
cd %~p1

1.3.複数引数の順次処理
複数のファイルを同時にcmdアイコンにドロップして,すべてのファイルについてある処理を行いたい場合には,
shift命令で,引数を順に捕まえることができる。
cmdファイル
:loop_start
if "%1"=="" goto :loop_end
call :mywork %~nx1
shift
goto :loop_start
:loop_end
pause
exit /b

:mywork
echo %~nx1

rem ここで1ファイルについて行う作業を記述する

echo completed successfully
echo.
exit /b



2.call の使い方
外部ファイルを関数として呼び出す
 call func1.cmd param1 param2

自分自身を関数として呼び出す
 call %0 KEYWORD param1 param2

自分自身内の関数を呼び出す
 call :myfunc1
  :
 exit /b

 :myfunc
  :
 exit /b

 callされる側の関数の終わりは「exit /b」でなければならない。

3.環境変数の設定と利用

文字列を代入する場合はset xxx=XXXX,利用するときは%xxx%
set myvar=Hello
echo %myvar%

値(整数)を代入するときはset /A xxx=1234,演算ができる
set /A mynum1=123
set /A mynum2=456
set /A mynum3=%mynum1%+%mynum2%

文字列をキーボードから入力する時は/P
set /P mystr="あなたの名前を入力してね >"
echo あなたの名前は%mystr%ですね

ファイルの1行目を環境変数に取り込む時も/P
set /p tmpdata=<.\tmptmptmp.txt

4.環境変数の文字列の一部置換
文字列の一部置換
@echo off
set myfname=test.txt
set myfname1=%myfname:txt=tmp%
echo %myfname%
echo %myfname1%
このCMDの実行結果は
test.txt
test.tmp
となる。

5.if の利用
条件により分岐する。
set str=abc
if %str%==abc (
    echo hello
) else (
    echo bye
)
このように使用することができるが,
()内にいろいろ書くと変数の更新タイミングの問題が生ずるので,サブルーチンを利用するのがよい。
変数の更新タイミングは()から脱出後になっている。
()内でerrorlevelの設定伴う命令を行っても,値の変更は()から脱出後になっている。

cmdファイル
@echo off
set str=abc
if %str%==abc (
    call :mysub1
) else (
    call :mysub2
)
echo %test%
if %str%==abcdefg (
    call :mysub1
) else (
    call :mysub2
)
echo %test%
pause
exit

:mysub1
set test=yes
exit /b
:mysub2
set test=no
exit /b

実行結果
yes
no

参考 比較演算子
 
equ 等しい
neq 等しくない
gtr より大きい
geq 以上
leq 以下
lss より小さい(=未満)


6.forの利用
6.1 ファイルから1行ずつ読みだして作業する

例ファイル ex.txt
1 abc Hello
2 def Good morning
3 ghi How are you

ex.txtを1行ずつ読みだして作業する。
tokens=1-3 は スペース,タブで区切られた文字列の最初の3つを,変数i,j,kに取り出す
1行取り出したら,変数の更新タイミングのトラブルを避けるために,サブルーチンを呼び出してしまう方が良い。

cmdファイル
@echo off
for /f "tokens=1-3" %%i in (ex.txt) do call :mysub %%i %%j %%k
echo %testtxt%
pause
exit

:mysub
echo %1 %2 %3
if %1==1 set testtxt=%2
exit /b

実行結果
1 abc Hello
2 def Good
3 ghi How
abc

A lss  B は,AはBより小さいの意味
cmdファイル
@echo off
set /a mynum=-999
set testtxt=
for /f "tokens=1-3" %%i in (ex.txt) do call :mysub %%i %%j %%k
echo %testtxt%
pause
exit

:mysub
echo %1 %2 %3
set /a n=%1
if %mynum% lss %n% set /a mynum=%n% & set testtxt=%2
exit /b

実行結果
1 abc Hello
2 def Good
3 ghi How
ghi


6.2 コマンドの実行結果を1行ずつ読みだして作業する
作業例として arp -a のコマンドを処理する。
そのままコマンドを実行すると次のようになっている状況で作業する。
>arp -a
インターフェイス: 192.168.1.18 --- 0x13
  インターネット アドレス 物理アドレス           種類
  192.168.1.1           00-0d-02-f8-cc-5c     動的
  192.168.1.4           00-1d-73-fd-08-17     動的
  192.168.1.5           b0-c7-45-5b-87-b0     動的
  192.168.1.6           b0-c7-45-5b-64-c0     動的
  192.168.1.10          8c-c1-21-8f-74-48     動的
  192.168.1.14          40-b8-37-02-70-06     動的
  192.168.1.200         00-23-18-be-38-60     動的
  192.168.1.202         00-11-32-49-9a-bf     動的
  192.168.1.255         ff-ff-ff-ff-ff-ff     静的
  224.0.0.22            01-00-5e-00-00-16     静的
  224.0.0.251           01-00-5e-00-00-fb     静的
  224.0.0.252           01-00-5e-00-00-fc     静的
  224.0.0.253           01-00-5e-00-00-fd     静的
  239.255.255.250       01-00-5e-7f-ff-fa     静的
  255.255.255.255       ff-ff-ff-ff-ff-ff     静的
"tokens=1,4,5 delims=. " は
ドット,スペースで区切られた文字列の,1,4,5番目のものを変数i,j,kとして取り出す。
cmdファイル
@echo off
for /f "tokens=1,4,5 delims=. " %%i in ('arp -a') do call :mysub %%i %%j %%k
pause
exit

:mysub
rem echo %1 %2 %3
if %1==192 if %2 neq 255 echo %2 %3
exit /b

実行結果
1 00-0d-02-f8-cc-5c
4 00-1d-73-fd-08-17
5 b0-c7-45-5b-87-b0
6 b0-c7-45-5b-64-c0
10 8c-c1-21-8f-74-48
14 40-b8-37-02-70-06
20 00-1d-73-fd-08-17
200 00-23-18-be-38-60
202 00-11-32-49-9a-bf

6.2 コマンドの実行結果を1行ずつ読みだしてまるごとsubに与えて作業する

作業例として ipconfig /all のコマンドを処理し必要な情報を表示する。
ipconfig /all の結果の一部をファイルtest.txtに保存して,実行することにする。
test.txtは次のようになっていることにする。
test.txt
Wireless LAN adapter Wi-Fi:

   接続固有の DNS サフィックス . . . . .: flats-north.jp
   説明. . . . . . . . . . . . . . . . .: Intel(R) Centrino(R) Advanced-N 6250 AGN
   物理アドレス. . . . . . . . . . . . .: 00-23-15-8E-57-8C
   DHCP 有効 . . . . . . . . . . . . . .: はい
   自動構成有効. . . . . . . . . . . . .: はい
   IPv6 アドレス . . . . . . . . . . . .: 2408:64:810a:0:7810:c6b0:73d6:6cc6(優先)
   一時 IPv6 アドレス. . . . . . . . . .: 2408:64:810a:0:7489:d684:241a:186c(優先)
   リンクローカル IPv6 アドレス. . . . .: fe80::7810:c6b0:73d6:6cc6%16(優先)
   IPv4 アドレス . . . . . . . . . . . .: 192.168.1.10(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   リース取得. . . . . . . . . . . . . .: 2018年10月25日 22:06:18
   リースの有効期限. . . . . . . . . . .: 2018年10月26日 2:06:17
   デフォルト ゲートウェイ . . . . . . .: fe80::20d:2ff:fef8:cc5c%16
                                          192.168.1.1
   DHCP サーバー . . . . . . . . . . . .: 192.168.1.1
   DHCPv6 IAID . . . . . . . . . . . . .: 83895061
   DHCPv6 クライアント DUID. . . . . . .: 00-01-00-01-1D-8E-6D-08-20-6A-8A-27-CB-1C
   DNS サーバー. . . . . . . . . . . . .: 2408:64:810a:0:20d:2ff:fef8:cc5c
                                          192.168.1.1
   NetBIOS over TCP/IP . . . . . . . . .: 有効
   接続固有の DNS サフィックス検索の一覧:
                                          flats-north.jp
                                          iptv.co.jp


1行丸ごと取り込むときは,オプションとして,"delims="をつける。
得られた1行をsubroutineに送るときは,
””で囲むこと。
囲まないと,受け取り側が%1で受け取った時,
最初のスペースまでしか受け取れないことになってしまう。

show_ip.cmd
@echo off
set more1=0
echo.
echo *****   ip settings   *****
rem for /f "delims=" %%i in ('ipconfig /all') do call :mysub "%%i"
for /f "delims=" %%i in (test.txt) do call :mysub "%%i"
pause
exit /b

:mysub
set tmp=%1
set line=%tmp:"=%
set line=%line:(R)=%

echo %line%|find "サフィックス検索" >nul
if %errorlevel% equ 0 (
  exit /b
)
echo %line%|find "接続固有の DNS サフィックス" |findstr /r /c:": $" >nul
if %errorlevel% equ 0 (
  exit /b
)
echo %line%|find "接続固有の DNS サフィックス"
echo %line%|find "IPv4 アドレス"
echo %line%|find "サブネット マスク"
echo %line%|find "デフォルト ゲートウェイ"|find ":"
if %errorlevel% equ 0 (
  set more1=1
  exit /b
)
echo %line%|find "サーバー"|findstr /r /c:"[0-9a-f]:[0-9a-f]"
if %errorlevel% equ 0 (
  set more1=1
  exit /b
)
echo %line%|findstr /r /c:"[0-9a-f]:[0-9a-f]" >nul
if %more1% == 1 (
  echo %line%
  if %errorlevel%==1 (
    set more1=0
  )
  exit /b
)
echo %line%|find "サーバー"
exit /b
実行結果
*****   ip settings   *****
   接続固有の DNS サフィックス . . . . .: flats-north.jp
   IPv4 アドレス . . . . . . . . . . . .: 192.168.1.10(優先)
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: fe80::20d:2ff:fef8:cc5c6
                                          192.168.1.1
   DHCP サーバー . . . . . . . . . . . .: 192.168.1.1
   DNS サーバー. . . . . . . . . . . . .: 2408:64:810a:0:20d:2ff:fef8:cc5c
                                          192.168.1.1