すごいDOSバッチ (コピペで)たのしく逃げよう!

  • 49
    いいね
  • 0
    コメント

「DOSバッチファイル」、嫌な響きですね...。

DOSバッチの作成依頼は、心の準備をしていないときに突然降って湧くもので、毎回毎回、for文の書き方をググってはハマり、環境変数の即時展開でハマり、「(の使い方が誤っています」「0の使い方が誤っています」等の言葉足らずのエラーに苦しめられる。こんな思い、二度としたくない。

でもいまさらDOSバッチの勉強なんてしたくない。

そんな時に備えて、DOSバッチでよく使うコードスニペットを用意しておきました。華麗にコピペで逃げましょう。

文字列操作等は関数化しています(結果の文字列は関数と同名の変数に格納されます)。勢いに乗って、Python的な文字列スライス関数(Slice)も作成しました。

バージョン情報
C:\>ver

Microsoft Windows [Version 6.1.7601]
コピペで逃げよう
@echo off
setlocal
rem ============================================================
rem 
rem main
rem 
rem ============================================================
rem このバッチファイルのカレントディレクトリへ移動
cd /d "%~dp0"

rem -------------------------------------------------------------
rem 前処理
rem -------------------------------------------------------------
rem バッチファイル名(拡張子つき)の取得
set prog_name="%~nx0"
echo %prog_name%を起動しました。

rem バッチファイル自身のフルパス(例:「C:\bat\sample.bat」)
set target_file="%~f0"
rem バッチファイルの格納先ディレクトリ(例:「C:\bat\」)
set target_dir="%~dp0"

rem ファイルの存在チェック
call :FileExist "%target_file%"
if %ERRORLEVEL% equ 1 (
    echo ファイル(%target_file%)が見つかりました。
) else (
    echo ファイル(%target_file%)が見つかりません。
    exit /b 1
)

rem ディレクトリの存在チェック
call :DirExist "%target_dir%"
if %ERRORLEVEL% equ 1 (
    echo ディレクトリ(%target_dir%)が見つかりました。
) else (
    echo ディレクトリ(%target_dir%)が見つかりません。
    exit /b 1
)

rem -------------------------------------------------------------
rem みんなに愛されてないFor文
rem -------------------------------------------------------------
rem 単語のイテレーション
for %%a in (aaa bbb ccc) do (
    set x=%%a
    call echo %%x%%
)

rem 整数のイテレーション
for /l %%a in (1,1,10) do (
    set x=%%a
    call echo %%x%%
)

rem ファイルのイテレーション
for %%a in (*.bat) do (
    set x=%%a
    call echo %%x%%
)

rem ファイルのイテレーション(サブディレクトリも再帰的に検索)
for /r %%a in (*.bat) do (
    set x=%%a
    call echo %%x%%
)

rem ディレクトリのイテレーション
for /d %%a in (*) do (
    set x=%%a
    call echo %%x%%
)

rem ディレクトリのイテレーション(サブディレクトリも再帰的に検索)
for /d /r %%a in (*) do (
    set x=%%a
    call echo %%x%%
)

rem CSVファイルの行イテレーション(各行のフィールド値をa,b,cに割り当て)
for /f "tokens=1-3 delims=," %%a in (sample.csv) do (
    echo [%%a %%b %%c]
)

rem コマンド実行結果の取得(例:CSVファイルの行数の取得)
set CMDSTR="type sample.csv | find /c /v """
for /f "usebackq delims=" %%a in (`%CMDSTR%`) do (
    set lines=%%a
)
echo %lines%

rem ファイル情報の取得
call :GetFileInfo .\sample.bat
echo %GetFileInfo.FileName%
echo %GetFileInfo.DirName%
echo %GetFileInfo.UpdateDate%

rem 数字列かの判定
call :IsNumeric 2147483647
echo IsNumeric 2147483647 =^> %ERRORLEVEL%
call :IsNumeric 214x483647
echo IsNumeric 214x483647 =^> %ERRORLEVEL%
call :IsNumeric -214x483647
echo IsNumeric -214x483647 =^> %ERRORLEVEL%

rem -------------------------------------------------------------
rem 文字列操作
rem -------------------------------------------------------------
echo ==== 文字列操作 ==================
rem 部分文字列の切り出し
call :SubStr abcdef 2 3
echo SubStr abcdef 2 3 =^> %SubStr%

rem 部分文字列の置換
call :Replace abcdef cde CDE
echo Replace abcdef cde CDE =^> %Replace%

rem 文字列の反転
call :Reverse ABCDEF
echo Reverse ABCDEF =^> %Reverse%

rem 小文字→大文字変換
call :UpCase abcdefg
echo UpCase abcdefg =^> %UpCase%

rem 大文字→小文字変換
call :DownCase ABCDEFG
echo DownCase ABCDEFG =^> %DownCase%

rem 文字列のスライス(インタフェース仕様はPythonと同じ)
call :Slice 123456789 "" "" -1
echo Slice 123456789 "" "" -1 =^> %Slice%

rem -------------------------------------------------------------
rem 年月日の取得
rem -------------------------------------------------------------
call :GetYear & call :GetMonth & call :GetDay & call :GetHour & call :GetMin & call :GetSec
echo GetYear ^(%DATE% %TIME%^) -^> [%GetYear%,%GetMonth%,%GetDay%,%GetHour%,%GetMin%,%GetSec%]

endlocal

exit /b 0

rem ============================================================
rem 
rem プロシージャ群
rem 
rem ============================================================
rem ============================================================
rem FileExist - ファイルの存在チェック(UNCパス/NFSパスにも対応)
rem ============================================================
:FileExist
    if exist "%1" (
        if not exist "%1\*" (
            exit /b 1
        )
    )
    exit /b 0

rem ============================================================
rem DirExist - フォルダの存在チェック(UNCパス/NFSパスにも対応)
rem ============================================================
:DirExist
    if exist "%1\*" (
        exit /b 1
    )
exit /b 0

rem ============================================================
rem GetFileInfo - ファイルの情報
rem ============================================================
:GetFileInfo
    set GetFileInfo.FilePath=%1

    for %%a in (%GetFileInfo.FilePath%) do (
        set GetFileInfo.FileName=%%~nxa
        set GetFileInfo.FileNameNoExt=%%~na
        set GetFileInfo.ExtName=%%~xa
        set GetFileInfo.DirName=%%~dpa
        set GetFileInfo.UpdateDate=%%~ta
        set GetFileInfo.FileSize=%%~za
    )
exit /b 0

rem ==============================================
rem StrLen - 文字数のカウント
rem ==============================================
:StrLen
    set _target=%1
    set _cou=0

    if not defined _target (
        set StrLen=0
        exit /b 0
    )

:__STRLEN_START__
    call set _target=%%_target:~1%%
    set /a _cou+=1
    if defined _target (
        goto __STRLEN_START__
    )

    set StrLen=%_cou%
exit /b 0

rem ============================================================
rem SubStr - 文字列の切り出し(0オリジン)
rem ============================================================
:SubStr
    set SubStr._target=%1
    set SubStr._start=%2
    set SubStr._length=%3
    call set SubStr=%%SubStr._target:~%SubStr._start%,%SubStr._length%%%
exit /b 0

rem ============================================================
rem Replace - 文字列置換(0オリジン)
rem ============================================================
:Replace
    set Replace._target=%1
    set Replace._old=%2
    set Replace._new=%3
    call set Replace=%%Replace._target:%Replace._old%=%Replace._new%%%
exit /b 0

rem ============================================================
rem Slice - 文字列スライス(インタフェース仕様はPythonと同じ)
rem ============================================================
:Slice
    set Slice._target=%1
    set Slice._start=%~2
    set Slice._end=%~3
    set Slice._step=%~4
    if not defined Slice._target (
        exit /b 0
    )

    call :StrLen %Slice._target%
    set /a Slice._target_len=%StrLen%

    rem ---------------------------------------
    rem デフォルト値の設定
    rem ---------------------------------------
    rem ステップ
    if not defined Slice._step (
        set /a Slice._step = 1
    )

    rem スタート・エンド
    if %Slice._step% geq 0 (
        if not defined Slice._start (
            set /a Slice._start = 0
        )
        if not defined Slice._end (
            set /a Slice._end = Slice._target_len
        )
    ) else (
        if not defined Slice._start (
            set /a Slice._start = Slice._target_len - 1
        )
        if not defined Slice._end (
            set /a Slice._end = Slice._target_len * -1 - 1
        )
    )

    rem ---------------------------------------
    rem スタート・エンドが負の数→正の数に変換
    rem ---------------------------------------
    if %Slice._start% lss 0 (
        set /a Slice._start += Slice._target_len
    )
    if %Slice._end% lss 0 (
        set /a Slice._end += Slice._target_len
    )
    rem ---------------------------------------
    rem エンドの調整
    rem ---------------------------------------
    if %Slice._step% geq 0 (
        set /a Slice._end -= 1
    ) else (
        set /a Slice._end += 1
    )

    set Slice._target_sliced=

    for /l %%a in (%Slice._start%,%Slice._step%,%Slice._end%) do (
        call set Slice._target_char=%%Slice._target:~%%a,1%%
        call set Slice._target_sliced=%%Slice._target_sliced%%%%Slice._target_char%%
    )

    set Slice=%Slice._target_sliced%

exit /b 0

rem ============================================================
rem Reverse - 文字列反転
rem ============================================================
:Reverse
    set Reverse._target=%1
    if not defined Reverse._target (
        exit /b 0
    )

    call :StrLen %Reverse._target% & set /a Reverse._target_len=%StrLen%-1
    set Reverse._target_rev=

    for /l %%a in (%Reverse._target_len%,-1,0) do (
        call set Reverse._target_char=%%Reverse._target:~%%a,1%%
        call set Reverse._target_rev=%%Reverse._target_rev%%%%Reverse._target_char%%
    )

    set Reverse=%Reverse._target_rev%

exit /b 0

rem ============================================================
rem DownCase - 大文字→小文字変換
rem ============================================================
:DownCase
    set DownCase._target=%1
    for %%a in (a b c d e f g h i j k l m n o p q r s t u v w x y z) do (
        call set DownCase._target=%%DownCase._target:%%a=%%a%%
    )
    set DownCase=%DownCase._target%
exit /b 0

rem ============================================================
rem UpCase - 小文字→大文字変換
rem ============================================================
:UpCase
    set UpCase._target=%1
    for %%a in (A B C D E F G H I J K L M N O P Q R S T U V W X Y Z) do (
        call set UpCase._target=%%UpCase._target:%%a=%%a%%
    )
    set UpCase=%UpCase._target%
exit /b 0

rem ============================================================
rem IsNumeric - 数字のみかの判定
rem ============================================================
:IsNumeric
    set IsNumeric._target=%~1

    if %IsNumeric._target:~0,1%==- (
        call set IsNumeric._target=%%IsNumeric._target:~1%%
    )

    for /l %%i in (0,1,9) do (
        call set IsNumeric._target=%%IsNumeric._target:%%i=%%
        if not defined IsNumeric._target (
            exit /b 1
        )
    )

    if not defined IsNumeric._target (
        exit /b 1
    )
exit /b 0

rem ============================================================
rem GetYear - 年の取得
rem ============================================================
:GetYear
    set GetYear=%DATE:~0,4%
exit /b 0

rem ============================================================
rem GetMonth - 月の取得
rem ============================================================
:GetMonth
    set GetMonth=%DATE:~5,2%
exit /b 0

rem ============================================================
rem GetDay - 日の取得
rem ============================================================
:GetDay
    set GetDay=%DATE:~8,2%
exit /b 0

rem ============================================================
rem GetHour - 時の取得
rem ============================================================
:GetHour
    set GetHour=%TIME:~0,2%
    set GetHour=%GetHour: =0%
exit /b 0
rem ============================================================
rem GetMin - 分の取得
rem ============================================================
:GetMin
    set GetMin=%TIME:~3,2%

rem ============================================================
rem GetSec - 秒の取得
rem ============================================================
:GetSec
    set GetSec=%TIME:~9,2%
exit /b 0