システムエンジニアの技術メモ

Windows バッチファイル/コマンドプロンプト

001. コマンド構文

▼コマンド リダイレクト演算子

リダイレクト演算子説明
>コマンド プロンプト ウィンドウやハンドルの代わりに、ファイルまたはデバイス (プリンタなど) にコマンドの出力を書き込みます。
<コマンドの入力を、キーボードやハンドルからの入力の代わりに、ファイルから読み取ります。
>>既にファイルにある情報を削除しないで、ファイルの最後にコマンドの出力を追加します。
>&あるハンドルからの出力を別のハンドルの入力に書き込みます。
<&あるハンドルからの入力を読み取り、別のハンドルの出力に書き込みます。
|あるコマンドからの出力を読み取り、別のコマンドの入力に書き込みます。パイプとも呼ばれます。

▼ハンドル

ハンドルハンドルに対応する数値説明
STDIN0キーボード入力。
STDOUT1コマンド プロンプト ウィンドウへの出力。
STDERR2コマンド プロンプト ウィンドウへのエラーの出力。
UNDEFINED3-9ハンドルはアプリケーションによって個別に定義され、各ツールで固有です。

▼複数のコマンドおよび条件付き処理記号

文字構文定義
&Command1 & Command2単一のコマンド ライン上の複数のコマンドを区切るために使います。1 つ目のコマンドが実行された後に、2 つ目のコマンドが実行されます。
&&Command1 && Command2&& 記号の前にあるコマンドが正常に終了した場合にのみ、この記号の後のコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが正常に終了した場合にのみ、2 つ目のコマンドが実行されます。
||Command1 || Command2|| 記号の前にあるコマンドが失敗した場合にのみ、後ろにあるコマンドを実行するために使います。1 つ目のコマンドが実行され、そのコマンドが失敗した場合 (コマンドから返されるエラー コードが 0 よりも大きい場合) にのみ、2 つ目のコマンドが実行されます。
( )(Command1 & Command2)複数のコマンドをまとめたり、ネストするときに使います。
; または ,Command1 Parameter1;Parameter2コマンドのパラメータを区切るときに使います。

▼上記の情報は Windows Server 2003 のヘルプに書いてあります。

「スタート」
 │
 └「ヘルプとサポート」
   │
   └「管理およびスクリプト ツール」
     │
     ├「コマンド ライン リファレンス」
     │ │
     │ └「リダイレクト演算子」
     │
     └「コマンド シェルの概要」

002. 実行ファイルのパス/名前/サイズ

FOR %%i IN (%0) DO (SET _file_path=%%~dpi) & (SET _file_name=%%~nxi) & (SET /A _file_size=%%~zi+0)
ECHO.
ECHO %_file_path%
ECHO.
ECHO %_file_name%
ECHO.
ECHO %_file_size%
ECHO.
PAUSE

003. 日時の取得

▽けっこうよく見かけます

SET _date=%date:/=-%

▽こっちのほうがスマートなように思います

FOR /F "tokens=1-3 delims=/-. " %%a IN ('date /t')    DO SET _date=%%a%%b%%c
FOR /F "tokens=1-3 delims=:. "  %%a IN ("%time: =0%") DO SET _time=%%a%%b%%c

004. 0バイトファイル作成

▽その1

TYPE NUL 0>test1.txt

▽その2

ECHO. 0>test2.txt

005. カレントディレクトリ内のフォルダを表示

FOR /D %%a IN (*) DO ECHO %%a

006. カレントディレクトリ内のファイルを表示

▽すべてのファイルを表示

FOR %%a IN (*) DO ECHO %%a

▽テキストファイルだけを表示(その1)

FOR %%a IN (*.txt) DO ECHO %%a

▽テキストファイルだけを表示(その2)

FOR /F "usebackq" %%a IN (`DIR /B *.txt`) DO ECHO %%a

▽テキストファイルだけを表示(その3)

FOR /F "usebackq tokens=1,2 delims=." %%a IN (`DIR /B *.txt`) DO ECHO %%a.%%b

007. FOR の使い方/テキストファイルを読む

SET _file=test.txt
FOR /F "skip=1 tokens=1,2 delims=," %%a IN (%_file%) DO SET _last_line=%%a

008. テキストファイルの1行目だけを読む

FOR と違い、全行を読まずに1行目だけを読んでいる。そのためサイズの大きいファイルでも早い。

SET /P _head=<test.txt
ECHO %_head%

009. カレントディレクトリ内のテキストファイルを結合

▽その1

COPY /B *.txt test.txt

▽その2

TYPE *.txt 1>test.txt

▽その3

TYPE NUL 0>test.txt
FOR /F "usebackq" %%i IN (`DIR /B *.txt`) DO TYPE %%i 1>> test.txt

010. テキストファイルのソート(並び替え)

sort.exe input_file.txt 1>output_file.txt

011. テキスト文字列を検索→結果出力

SET _find_string=test
SET _input_file=aaa.txt
SET _output_file=bbb.txt

REM - /I : 大文字と小文字を区別しない
find.exe /I "%_find_string%" < %_input_file% > %_output_file%

012. ファイル/ディレクトリのリスト出力

▽ファイルのリスト

DIR /B *.xls 1>list.txt

▽ディレクトリのリスト

DIR /B /A:D 1>list.txt

▽サブディレクトリを含むディレクトリのリスト

DIR /B /A:D /S 1>list.txt

013. 時刻合わせ

▽その1(タイムサーバー)

SET _time_server=ntp.jst.mfeed.ad.jp
net.exe STOP W32Time
net.exe TIME /SETSNTP:%_time_server%
net.exe START W32Time
net.exe STOP W32Time

▽その2(ドメイン)

SET _domain=domain.local
net.exe TIME /DOMAIN:%_domain% /SET /Y

014. PING の使い方

REM - 疎通確認
ping.exe 127.0.0.1
ping.exe www.yahoo.co.jp
REM - ホスト名確認/-a
ping.exe -a 127.0.0.1
REM - 無限リトライ/-t
REM - 中断するには Ctrl+C
ping.exe -t 127.0.0.1
REM - 10回リトライ/-n
ping.exe 127.0.0.1 -n 10
REM - 約3秒待つ
ping.exe -n 3 localhost 0>NUL

※ICMP(Internet Control Message Protocol) が遮断されていると PING は使えない

015. リモート接続/リモートドライブ接続

SET _server=192.168.0.1
SET _domain=localhost
SET _uid=administrator
SET _pwd=password

REM - リモート接続確認
net.exe USE

REM - 別のアカウントでリモート接続
net.exe USE \\%_server%\C$ /USER:%_domain%\%_uid% %_pwd%

REM - リモート切断
net.exe USE /D \\%_server%\IPC$

REM - 別のアカウントでリモートドライブ接続
net.exe USE Z: \\%_server%\C$ /USER:%_domain%\%_uid% %_pwd% /PERSISTENT:NO

REM - リモートドライブ切断
net.exe USE /D Z:

016. 異なるアカウントで実行/runas

SET _domain=localhost
SET _uid=administrator
SET _application=explorer.exe

runas.exe /netonly /user:%_domain%\%_uid% %_application%

017. ネットワーク設定/netsh

SET _netsh_file=temp.netsh

REM - 設定ファイル出力
netsh.exe -c interface dump > %_netsh_file%

REM - 設定ファイルの読み込み
netsh.exe -f %_netsh_file%

018. EUC, UTF-8 で FTP

REM - フォント[MS ゴシック]
REM - [EUC-JP]
CHCP 20932
REM - [UTF-8]
REM - CHCP 65001

SET _ftp_server=192.168.0.1
SET _ftp_user=administrator
SET _ftp_pass=password
SET _ftp_script=_ftp_script.ftp
SET _log_file=log_file.log

ECHO open %_ftp_server% >  %_ftp_script%
ECHO %_ftp_user%        >> %_ftp_script%
ECHO %_ftp_pass%        >> %_ftp_script%
ECHO cd dir_put         >> %_ftp_script%
ECHO dir                >> %_ftp_script%
ECHO bin                >> %_ftp_script%
ECHO put file1.cab      >> %_ftp_script%
ECHO ascii              >> %_ftp_script%
ECHO put file2.txt      >> %_ftp_script%
ECHO dir                >> %_ftp_script%
ECHO bye                >> %_ftp_script%

ftp.exe -s:%_ftp_script% 1>"%_log_file%"

019. 100分割実行.bat

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- 開始処理
ECHO ▽はじめ! 1>100分割実行.txt

:-- 100分割
FOR /L %%i IN (0,1,99) DO (SET _nn=0%%i) & (SET _nn=!_nn:~-2!) & (CALL :sub_split)

:-- 終了処理
ECHO △おわり! 1>>100分割実行.txt
EXIT

:-- 分割実行
:sub_split
ECHO _nn=%_nn% 1>>100分割実行.txt
EXIT /B

020. バッチで「日付の形式」に対応する

Windows の言語によってデフォルトの日付形式が異なる。

短い日付の形式をレジストリから読み取り、yyyy/MM/dd, MM-dd-yy などの異なるフォーマットでも一つのバッチで対応できるようにしたもの。

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- 地域と言語 > 日付の形式(短い形式)
FOR /F "tokens=1-2*" %%a IN ('reg query "HKCU\Control Panel\International" /v sShortDate') DO IF "%%a"=="sShortDate" SET _format=%%c

FOR /F "tokens=1-5 delims='" %%a IN ("%_format%") DO SET _format=%%a%%b%%c%%d%%e

FOR /F "tokens=1-5 delims=/-.() " %%A IN ("%_format%") DO (
    FOR /F "tokens=1-5 delims=/-.() " %%a IN ("%date%") DO (
      (SET _%%A=%%a) & (SET _%%B=%%b) & (SET _%%C=%%c) & (SET _%%D=%%d) & (SET _%%E=%%e)
    )
)

:-- 年 > 4桁
FOR /F "tokens=1-2*" %%a IN ('reg query "HKCU\Control Panel\International\Calendars\TwoDigitYearMax"') DO SET _TwoDigitYearMax=%%c

IF "%_yyyy%"=="" (
    IF "%_yy%" LEQ "!_TwoDigitYearMax:~-2!" (
        SET /A _yyyy = !_TwoDigitYearMax:~0,2!
    ) ELSE (
        SET /A _yyyy = !_TwoDigitYearMax:~0,2! - 1
    )
    SET _yyyy=!_yyyy!%_yy%
)

:-- 月日 > 2桁
IF "%_MM%"=="" (SET _MM=0%_M%) & (SET _MM=!_MM:~-2!)
IF "%_dd%"=="" (SET _dd=0%_d%) & (SET _dd=!_dd:~-2!)

:-- セットした変数の表示
SET _

PAUSE

※変数 _yy と _YY は異なるため、Windows のバージョンによっては修正する必要があるかも知れない

021. UNC パスでバッチを実行

「UNC パスはサポートされません。Windows ディレクトリを既定で使用します。」

を回避

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- 実行パスをBドライブに割り当て
IF "%~d0"=="\\" (SET _path=%~dp0) & (NET USE B: "!_path:~0,-1!") & (B:)

:-- コマンド実行
DIR

:-- ネットワークドライブ切断
(C:) & (NET USE B: /DELETE /Y)

PAUSE

022. ドライブの空き領域をログファイルに出力

実行日時と空き領域を1行に出力したい

▽その1

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- ドライブの空き領域
(FOR /F "usebackq delims=*" %%a IN (`DIR %~d0`) DO SET drive_free=%%a) & (@ECHO %date% %time% !drive_free!)>>%~dp0drive_free.log

▽その2

FOR /F "usebackq delims=*" %%a IN (`DIR %~d0 ^| FIND "空き領域"`) DO (@ECHO %date% %time% %%a)>>drive_free.log

その2だと、

1.フォルダ名・ファイル名に"空き領域"が入っていると余計な行が出力されてしまう

2.日本語環境でしか使えない

023. 文字列の長さ(バイト数)を取得、文字数を取得

▽CHCP で使える CodePage

 ・HKLM\SYSTEM\CurrentControlSet\Control\Nls\CodePage

 ・C:\Windows\System32 の *.NLS ファイル

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

@ECHO OFF

:-- バイト数を取得(CHCP 437 の後に SET _string を行う)
CHCP 437
SET _string=テスト
CALL :_get_length %_string%
CHCP 932
@ECHO ◆長さ=%_len%

:-- 文字数を取得
CHCP 932
SET _string=テスト
CALL :_get_length %_string%
@ECHO ◆文字数=%_len%

PAUSE
EXIT

:_get_length
SET _str=%1
SET _len=0
:_loop
IF "%_str%"=="" EXIT /B
SET _str=%_str:~1%
SET /A _len=%_len%+1
GOTO :_loop

024. 引数(YYYYMM)を受け取り、月末(YYYYMMDD)を返す (bat + vbs)

LAST_DAY.bat から LAST_DAY.vbs を呼び出し、標準出力(ECHO)をバッチで受け取る。

--

LAST_DAY.vbs

'// Arguments : (0)YYYYMMDD
Set objArgs = WScript.Arguments

'// YYYY, MM
If objArgs.Count = 0 Then
    yyyy = Year(Date)
    mm = Month(Date)
Else
    yyyy = Mid(objArgs(0), 1, 4)
    mm = Mid(objArgs(0), 5, 2)
End If

WScript.Echo Replace(DateSerial(yyyy, mm + 1, 0), "/", "")

LAST_DAY.bat

SET _date=20000201
FOR /F "usebackq" %%a in (`cscript //nologo LAST_DAY.vbs %_date%`) DO SET _last_day=%%a
SET _
PAUSE

025. net use で ネットワーク切断/切断するものを一覧から選択

完璧なコードではないので仕様を理解して使うべし。

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

@ECHO OFF
TITLE %~nx0

:_net_use
SET _no=0

FOR /F "usebackq delims=" %%a IN (`CHCP 437 ^| net use ^| FINDSTR /L "\\"`) DO (
    IF !_no!==0 @ECHO ----- NET USE -----
    SET _line=%%a
    IF "!_line:~-25!"=="Microsoft Windows Network" SET _line=!_line:~0,-25!
    SET /A _no=!_no!+1
    SET _disp_no=   !_no!
    SET _disp_no=!_disp_no:~-4!
    SET _drive=!_line:~13,2!
    SET _remote=!_line:~23!
    CALL :_trim_remote !_remote!
    IF "%_select%"=="" @ECHO !_disp_no!  !_drive!  !_remote!
    IF "%_select%"=="!_no!" IF "!_drive!"=="  " (net use /d "!_remote!") ELSE (net use /d !_drive!)
)

IF NOT "%_select%"=="" (
    SET _select=
    CHCP 932
    GOTO :_net_use
)

SET /P _select="Select the number to disconnect  [Blank] EXIT >"
IF "%_select%"=="" EXIT
GOTO :_net_use

:_trim_remote
SET _remote=%*
EXIT /B

026. 実行ファイルのフォルダ名

▽ローカル

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- フォルダ名
(SET _path0=!CD!) & (CD..) & (SET _path1=!CD!\) & (CD %~dp0)
CALL SET _folder=%%_path0:%_path1%=%%

SET _
PAUSE

▽ネットワーク

@ECHO OFF

SET _pos1=0
SET _path=%~dp0
SET _path=%_path:~0,-1%

:-- 最後の"\"の位置
:_loop
CALL SET _substr=%%_path:~%_pos1%,1%%
SET /A _pos1=%_pos1%+1
IF "%_substr%"=="" GOTO :_next
IF "%_substr%"=="\" SET _pos2=%_pos1%
GOTO :_loop

:_next
CALL SET _folder=%%_path:~%_pos2%%%

SET _
PAUSE

027. CSV作成 「utf-8+LF+EOF直前の改行なし」

▽HEADER.txt

日付,社員番号,ファイル名,※BOMの有無はこのファイルで設定する

▽CSV作成.bat

:-- 遅延環境変数を有効にする
SETLOCAL EnableDelayedExpansion

:-- システム日付
FOR /F "tokens=1-3 delims=/-. " %%a IN ('date /t') DO (SET _yyyy=%%a) & (SET _mm=%%b) & (SET _dd=%%c)

:-- 改行コード(LF) ※2行空ける
SET LF=^


:-- 出力ファイル
SET _FILE="給与明細一覧.csv"

:-- 文字セット(utf-8)
CHCP 65001

:-- ヘッダー部
TYPE HEADER.txt > %_FILE%

:-- データ部
SET _data=
FOR /F "usebackq tokens=1-3 delims=_" %%a IN (`DIR /B *.pdf`) DO (SET _data=!_data!!LF!!_mm!/!_dd!/!_yyyy!^,%%b^,%%a_%%b_%%c)
(SET /P =!_data!) < NUL >> %_FILE%
サンプルファイル (2KB)