Windowsバッチ(.bat)学習メモ　7zipで指定月数前に出力されたものを圧縮・bkフォルダへ移動・圧縮元を削除する処理

※「出力されたもの」は、その名称に、
出力された日の日付がyyyymmdd形式で含まれているものとする
（例：dailyLog_**20250204**112334.txt）

```bat:bat起動時の日付と時刻を取得（yyyymmdd_hhmmss_ss形式）
set a=0%time::=%
set a=!a:.=_!
set startDateAndTime=%date:/=%_!a:~-9!
```

```bat:ログ出力準備
setlocal enabledelayedexpansion

rem--------------------------------------------------
::ログ出力先フォルダのフォルダ名
set logDirName=logs
::ログのファイル名
set firstLogName=log1
set secondLogName=log2
rem--------------------------------------------------

::ログ出力可能フラグをOFFに
set canOutputLog=0

::ログ用フォルダが既存かどうか確認
set logDir="%~dp0%logDirName%"
dir %logDir% >nul 2>nul
::既存でなかった場合、作成
if %errorlevel% EQU 1 (
    mkDir %logDir%
::作成に失敗した場合、終了
    if %errorlevel% EQU 1 (
        exit
    )
)

::ログ用フォルダ内に、今処理のログ用フォルダを作成
set logDir="%logDir:"=%\%startDateAndTime%"
::"
mkDir %logDir%
::作成に失敗した場合、終了
if %errorlevel% EQU 1 (
    exit
)

::ログファイルパス取得
set firstLogName=%firstLogName%.log
set firstLog=%logDir%\%firstLogName%
set secondLogName=%secondLogName%.log
set secondLog=%logDir%\%secondLogName%
::出力が可能か確認
set logs[0]=%firstLog%
set logs[1]=%secondLog%
for /l %%i in (0,1,1) do (
    set nowLog=!logs[%%i]!
    echo.>>!nowLog!
    dir !nowLog! >nul 2>nul
    if !errorlevel! EQU 1 (
        exit
    )
)

::ログ出力可能フラグをONに
set canOutputLog=1
```

```bat:実行時年月から、指定された月数ぶん前の年月をyyyymm形式で取得
rem--------------------------------------------------
set elapsedMonths=4
rem--------------------------------------------------

call :getTgtYYYYMM

rem--------------------------------------------------
:getTgtYYYYMM
::指定された月数が適切か（=自然数か）を確認
powershell -command "if([regex]::IsMatch('%elapsedMonths%', '^[1-9][0-9]*$')) {exit 0} else {exit 1}" >nul 2>nul
if %errorlevel% EQU 1 (
    exit
)
::実行時年月を取得
set nowY=%date:~0,4%
set nowM=%date:~5,2%
::指定された月数を、年数と月数に分割
set /a orderedY=%elapsedMonths%/12
set /a orderedM=%elapsedMonths%%%12
::実行時年月から、指定された月数ぶん前の年月を取得
set /a tgtY=%nowY%-%orderedY%
if %nowM% LEQ %orderedM% (
    set /a tgtM=%nowM%+12-%orderedM%
    set /a tgtY=%tgtY%-1
) else (
    set /a tgtM=%nowM%-%orderedM%
)
set tgtYYYYMM=0%tgtM%
set tgtYYYYMM=%tgtY%%tgtYYYYMM:~-2%
exit /b
rem--------------------------------------------------
```

```bat:実施前確認
```









<details><summary>2025/02/04</summary>
日次や週次で生成されるフォルダ群のうち、ｎヵ月前のものを圧縮する処理。

※想定
・圧縮対象は、生成日次を用いた「yyyymm」を名称に含むようなフォルダである
・圧縮により生成された7zファイルは、圧縮元が存在するディレクトリ配下のbackup\yyyymm\yyyymm.7z、へ配置される。（yyyymmは、ｎヵ月前の年月をyyyymm形式で表したもの）
・同じ階層に、呼び出し元（Controller.bat）も、呼び出され側（Service.bat）も、両方存在している前提

<br>

```bat:Controller.bat
@echo off
setlocal enableDelayedExpansion

::ーーーーーーーーーーーーーーーーーーーーーーーーー

rem コンフィグ

::◆この処理の中核となるbatファイルのパス
set serviceBatFileName=service.bat
set serviceBat=%cd%\%serviceBatFileName%

::◆この処理の対象となるディレクトリのパス
set cmnPath=（パス）
set tgtDir[1]=!cmnPath!\（圧縮したいものがいるディレクトリのパス１）
set tgtDir[2]=!cmnPath!\（圧縮したいものがいるディレクトリのパス２）
set tgtDir[3]=!cmnPath!\（圧縮したいものがいるディレクトリのパス３）

::◆7zipの実行ファイルのパス
set zipper=（「7-Zip\7z.exe」のパス）

::◆圧縮するファイルが、実行時のnヵ月前なのかを指定
set howManyMonthAgo=（12以下の任意の自然数）

::ーーーーーーーーーーーーーーーーーーーーーーーーー

rem 変数準備

::◆実行時の年月日を取得（それぞれyyyy、mm、dd形式）
set yyyyNow=%date:~0,4%
set mmNow=%date:~5,2%
set ddNow=%date:~8,2%

::◆実行時のnヵ月前の年月を取得（それぞれyyyy、mm形式）
if %mmNow% leq %howManyMonthAgo% (
    set /a mmTgt=%mmNow%+(12-%howManyMonthAgo%)
    set /a yyyyTgt=%yyyyNow%-1
) else (
    set /a mmTgt=%mmNow%-%howManyMonthAgo%
    set yyyyTgt=%yyyyNow%
)
set mmTgt=0!mmTgt!
set mmTgt=!mmTgt:~-2!

::ーーーーーーーーーーーーーーーーーーーーーーーーー

rem 実行前確認

:reQuestion
echo このbatは、（手順の概要）を自動実行するものです。
set /p answer=処理を実行してもよろしいですか？[y/n]
if "!answer!"=="y" (
    goto exeProcess
) else (
    if "!answer!"=="n" (
        echo 処理の実行が拒否されました。
        goto processAllFinish
    ) else (
        echo 「y」または「n」で回答してください。
        goto reQuestion
    )
)

::ーーーーーーーーーーーーーーーーーーーーーーーーー

:exeProcess
echo.
echo ★★★全体処理開始★★★

rem ※呼び出され側に渡す引数の内容
:: 第一引数＝圧縮対象が存在するディレクトリのパス
:: 第二引数＝圧縮対象の名前（後にdirコマンドで検索をかけるため、ワイルドカードによる指定も可能）
:: 第三引数＝圧縮後の7zファイルのパス
:: 第四引数＝実行する7zExeのパス
:: 第五引数＝実行時のnヵ月前（yyyymm形式）

rem 処理実行
for /l %%i in (1,1,（処理の対象となるディレクトリの総数）) do (
    rem ◆処理対象ごとに値を用意（圧縮対象が存在するディレクトリのパス）
    set tgtDir=!tgtDir[%%i]!
    rem ◆処理対象ごとに値を用意（7zファイル配置場所）
    set zippedFileName=!tgtDir!\backup\%yyyyTgt%\%yyyyTgt%%mmTgt%.7z
    rem ◆処理対象ごとに値を用意（圧縮対象の名前）
    set searchTgt=!tgtDir!\%yyyyTgt%%mmTgt%*

    rem ◆処理
    echo.
    echo ～～～～～%%i個めの処理開始～～～～～
    echo 【対象環境：!zippedFIleName!】
    call %serviceBat% !tgtDir! !searchTgt! !zippedFIleName! !zipper! %yyyyTgt%%mmTgt%
    echo ～～～～～%%i個めの処理終了～～～～～
    echo.
)

echo ★★★全体処理終了★★★

::ーーーーーーーーーーーーーーーーーーーーーーーーー

pause
```

<br>

```bat:呼び出される側.bat
@echo off
setlocal enableDelayedExpansion

rem コンフィグ
set logDir=（ログを出力させたいパス）
set zipTargetListLogName=（圧縮対象の名前のリストを記すファイルの名前）
set zipExeLogName=（7z実行時ログを記すファイルの名前）
set workDirName=（作業フォルダの名前）

rem 引数をチェック
if "%1"=="" (
    echo 引数がありません。
    goto processStop
) else (
    if "%2"=="" if "%3"=="" if "%4"=="" if "%5"=="" (
        echo 引数が不足しています。
        goto processStop
    ) else (
        set tgtDir=%1
        set searchTgt=%2
        set zippedFileName=%3
        set zipper=%4
        set yyyymm=%5
    )
)

rem 作業フォルダを作成
::◆実行時の時刻を取得（hhmmss_mm形式）
set startExeTime=0%time::=%
set startExeTime=!startExeTime:.=_!
set startExeTime=!startExeTime:~-9!
::◆フォルダを作成
set workDir=%tgtDIr:"=%\%workDirName%\%startExeTime%実施分
::" "マークダウン上のコメントアウト化回避用ダブルクォート 実働時には消しても問題ない"
if not exist %workDir% (
    mkdir "%workDir%\%yyyymm%" /p
)

rem 圧縮対象を検索し、一か所にまとめる
set count=0
for /f "delims=" %%a in ('dir /b /ad %zipTarget%') do (
    set /a count+=1
    set beforeZipFile=%tgtDir:"=%\%%a
    ::" "マークダウン上のコメントアウト化回避用ダブルクォート 実働時には消しても問題ない"
    move "!beforeZipFile!" "%workDir%\%yyyymm%" >nul
    echo "!beforeZipFile!" >> "%logDir%\%zipTargetListLogName%.log"
)

rem まとめたフォルダを、実際に圧縮する（対象が無ければ、なにもしない）
if !count!==0 (
    echo 圧縮対象はありませんでした。
    goto deleteWorkDir
) else (
    echo !count!個の対象が見つかりました。
    echo 【!zippedFileName!】への圧縮を実行します。
    echo 圧縮には時間がかかります。しばらくお待ちください...
    %zipper% a -mx=9 -mmt=on !zippedFileName! "%workDir%\%yyyymm%" >> "%logDir%\%zipExeLogName%.log"
    msg * "圧縮が完了しました。"
    echo 圧縮が完了しました。
)

rem 圧縮対象を一か所にまとめたものを、削除するか確認する
:reQuestion
'dir /b /ad %zipTarget%'
set /p answer=これらの圧縮対象を削除してもよろしいですか？[y/n]
if "!answer!"=="y" (
    echo 圧縮対象を削除します。しばらくお待ちください...
    goto deleteWorkDir
) else (
    if "!answer!"=="n" (
        echo 削除が拒否されました。
        echo 後に削除する場合、圧縮対象は下記にまとまっていますのでこちらを参照してください。
        echo "%workDir%\%yyyymm%"
        goto processFinish
    ) else (
        echo 「y」か「n」で入力してください。
        goto reQuestion
    )
)

rem 圧縮対象を削除
:deleteWorkDir
rmdir /s /q "%tgtDir:"=%\%workDirNamr%"
::" "マークダウン上のコメントアウト化回避用ダブルクォート 実働時には消しても問題ない"
msg * "完了"
echo 完了
goto processFinish

rem 終了
:processStop
echo 処理を中止しました。
:processFinish
pause
exit /b
```
</details>