WordPress バックアップ その3

 その2でログファイルなどを一定数以上のを削除するようにしたが、cmd.exeの変数を使っているため長いファイル名や個数が多くなるとエラーが出て実行できなくなる。

 変数ではなく最初からファイルに書き出すことで制限を実質上無くする。

 ソート用ファイルにファイルサイズも出力した。PrintNum3.batファイルがあれば3桁区切りで,を追加する。

Backup.bat

@echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
@rem DATEの出力で、先頭に曜日が漢字一文字で表示されることがある。
@rem その場合は設定-時計と言語-日付と時刻-日付と時刻の形式を変更するで、
@rem 日付(短い形式)でyyyy/MM/ddを選ぶと曜日が出力されなくなるようだ。
@rem OSのバージョンによっては、設定-時刻と言語-日付と時刻-日付、時刻、地域の書式設定-データ形式を変更する

setlocal

cd /D %~dp0
if not exist %~dp0log mkdir %~dp0log

set LOGFILE=%~dp0log\%COMPUTERNAME%_Backup_%date:~-10,4%-%date:~-5,2%-%date:~-2,2%.log

if "%WORDPRESS_BACKUP%" == "" (
    echo no backup placement >> %LOGFILE% 2>&1
    echo set WORDPRESS_BACKUP=xxx >> %LOGFILE% 2>&1
    endlocal

    EXIT /B
)

if not exist %LOGFILE% (
    if exist "\ProgramData\Win-acme" (
      echo robocopy  "\ProgramData\Win-acme" "%WORDPRESS_BACKUP%\ProgramData\Win-acme" /MIR /NP /XD log >> %LOGFILE% 2>&1
           robocopy  "\ProgramData\Win-acme" "%WORDPRESS_BACKUP%\ProgramData\Win-acme" /MIR /NP /XD log >> %LOGFILE% 2>&1
    )

    for %%f in (Squid xampp) do call %0 %%f
      if exist \%%f (
        echo robocopy  \%%f %WORDPRESS_BACKUP%\%%f /S /XJ /XO /XX /XL /NP
        robocopy  \%%f %WORDPRESS_BACKUP%\%%f /S /XJ /XO /XX /XL /NP
      )
    ) >> %LOGFILE% 2>&1

    call BackupMySQL.bat 30d >> %LOGFILE% 2>&1

    call DeleteOldFile.bat %~dp0log %COMPUTERNAME%_backup_*.log 30d >> %LOGFILE% 2>&1

    call DeleteOldFile.bat C:\ProgramData\win-acme\acme-staging-v02.api.letsencrypt.org\Log log-*.txt 90d >> %LOGFILE% 2>&1
    call DeleteOldFile.bat C:\ProgramData\win-acme\acme-v02.api.letsencrypt.org\Log         log-*.txt 90d >> %LOGFILE% 2>&1

    call DeleteOldFile.bat C:\Temp\sakura   *.* 30d >> %LOGFILE% 2>&1
    call DeleteOldFile.bat C:\Temp\WinMerge *.* 30d >> %LOGFILE% 2>&1
)

endlocal

EXIT /B

BackupMySQL.bat

@echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
rem MAX_FILES 残す個数


setlocal

for %%i in (wp-01 wp-02) do call :MYSQLDUMP %%i %1

endlocal

EXIT /B


:MYSQLDUMP

setlocal

if not exist %~dp0MySQL mkdir %~dp0MySQL
set SQL_FILE=%~dp0MySQL\%COMPUTERNAME%_%1_%date:~-10,4%-%date:~-5,2%-%date:~-2,2%.sql

if not exist %SQL_FILE% (
    echo C:\xampp\mysql\bin\mysqldump -u -p %1
    C:\xampp\mysql\bin\mysqldump -u ユーザー名 -pパスワード %1 > %SQL_FILE%
    if errorlevel 1 goto :NO_FILE
    
    for %%f in (%SQL_FILE%) do (
        if %%~zf == 0 goto :NO_FILE
        if "%%~zf" == "" goto :NO_FILE
    )

    if not "%WORDPRESS_BACKUP%" == "" (
        if not exist %WORDPRESS_BACKUP%\xampp\Tools\MySQL mkdir %WORDPRESS_BACKUP%\xampp\Tools\MySQL
        echo copy /Y %SQL_FILE% %WORDPRESS_BACKUP%\xampp\Tools\MySQL\
        copy /Y %SQL_FILE% %WORDPRESS_BACKUP%\xampp\Tools\MySQL\
    )

    call DeleteOldFile.bat %~dp0MySQL %COMPUTERNAME%_%1_*.sql %2
)

endlocal

EXIT /B

:NO_FILE

echo SQL output fail.

endlocal

EXIT /B 1

 DeleteOldFile.bat

@echo off
@rem echo %0 %1 $2 %3 %4
if not "%4" == "" goto :FORMAT
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
@rem FOLDER フォルダー
@rem PATERN ファイルパターン
@rem        最後の文字が"\"ならフォルダーパターン
@rem LAST_DAYS 残す日数d or MAX_FILES 残す個数n デフォルトは日数

setlocal enabledelayedexpansion

set FOLDER=%~1
set PATERN=%~2
set PARAM3=%3
set /a MAX_FILES=0
set /a LAST_DAYS=0
set DIRECTORY=
if "%PATERN:~-1%" == "\" set DIRECTORY=/d
if "%PATERN:~-1%" == "\" set PATERN=%PATERN:~0,-1%
echo DIRECTORY="%DIRECTORY%" PATERN="%PATERN%"

@rem forfilesに*.*を指定すると拡張子無しが検索できないので*に変える
if "%PATERN%" == "*.*" set PATERN=*

@rem 日付(d)、個数(n)指定の処理、指定されていないときは日付指定にする
if not "%PARAM3%" == "" (
  if /I "%PARAM3:~-1%" == "d" (
    set /a LAST_DAYS=%PARAM3:~0,-1%
  ) else if /I "%PARAM3:~-1%" == "n" (
      set /a MAX_FILES=%PARAM3:~0,-1%
  ) else (
     set /a LAST_DAYS=%PARAM3%
  )
)

if not exist %FOLDER% (
  echo not exist %FOLDER%
  endlocal
  echo.
  EXIT /B 1
)

if %MAX_FILES% LEQ 0 IF %LAST_DAYS% LEQ 0 (
  echo bad option
  echo usage: [folder] [pattern] [daysD or countN]
  endlocal
  echo.
  EXIT /B 1
)

:TEMP_NAME
set TEMPI_FILE=%TEMP%\%~n0_I%RANDOM%.tmp
set TEMPO_FILE=%TEMP%\%~n0_O%RANDOM%.tmp
if exist %TEMPI_FILE% goto :TEMP_NAME
if exist %TEMPO_FILE% goto :TEMP_NAME


set TARGET_TIME=
@rem 環境によっては「'FileSystem' プロバイダーで InitializeDefaultDrives 操作を実行しようとして失敗しました。」とエラー表示されるので、エラー出力を無視する
if %LAST_DAYS% GTR 0 FOR /F "usebackq delims=" %%a in (`powershell "(get-date).AddDays(-%LAST_DAYS%).ToString(\"yyyy-MM-ddTHH:mm:ss\")"2^>nul`) do Set TARGET_TIME=%%a

@rem if exist *.*は常にTRUEになるので、ファイルの数を数える
@rem if not exist %FOLDER%\%PATERN% goto :DONE
set /a COUNT=0
for %DIRECTORY% %%a in ("%FOLDER%\%PATERN%") do set /a COUNT+=1 > NUL

echo MAX_FILES=%MAX_FILES% LAST_DAYS=%LAST_DAYS% TARGET_TIME=%TARGET_TIME% COUNT=%COUNT%


if %COUNT% equ 0 goto :DONE

@rem ファイルのタイムスタンプを秒まで欲しいため、firfilesで出力させる
@rem firfilesがUNCに対応していないので、一旦カレントディレクトリに変える
@rem %0がパスを含んでいないこともあるので%~f0と記述
pushd "%FOLDER%" && (
    forfiles /M "%PATERN%" /C "cmd /c %~f0 \"@fdateT@ftime\" @file @fsize %TEMPI_FILE%"
  popd
)

@rem 日数指定の場合は日時だけの行を追加しておく
if not "%TARGET_TIME%" == "" echo "%TARGET_TIME%">> %TEMPI_FILE%

@rem 逆順にソートする
sort.exe /R %TEMPI_FILE% /O %TEMPO_FILE%
if ERRORLEVEL 1 goto :SORT_ERR
for %%f in (%TEMPO_FILE%) do (
  if %%~zf == 0 goto :SORT_ERR
  if "%%~zf" == "" goto :SORT_ERR
)

echo type %TEMPO_FILE%
type %TEMPO_FILE%


if not "%TARGET_TIME%" == "" goto :DAYS

@rem 個数指定での削除
set /a FILE_COUNT=0
for /F "delims=" %%g in (%TEMPO_FILE%) do (
  set /a FILE_COUNT=!FILE_COUNT! + 1
  if !FILE_COUNT! GTR %MAX_FILES% (
    CALL :SUB_DELETE %%g
  )
)
goto :DONE

:DAYS
@rem 日付指定での削除
@rem 日付のみのがあればそれ以降を削除する
set DELETE=
for /F "delims=" %%g in (%TEMPO_FILE%) do (
  if not "!DELETE!" == "" (
    CALL :SUB_DELETE %%g
  ) else (
    set FILE_TIME=%%g
    if "!FILE_TIME!" == ""%TARGET_TIME%"" (
rem      echo delete point !FILE_TIME!
      set DELETE=1
    )
  )
)
goto :DONE


:SUB_DELETE
  setlocal enabledelayedexpansion
  for /F "tokens=2 delims=+" %%b in (%1) do (
    set FILE=%%b
    set FILE=!FILE:"=!
rem   echo dir "%FOLDER%\!FILE!"
rem        dir "%FOLDER%\!FILE!"
    if "%DIRECTORY%" == "" (
      echo del "%FOLDER%\!FILE!"
           del "%FOLDER%\!FILE!"
    ) else (
      echo rd /S /Q "%FOLDER%\!FILE!"
           rd /S /Q "%FOLDER%\!FILE!"
    )
  )
  endlocal
exit /b

:SORT_ERR
echo sort error
if exist %TEMPI_FILE% del %TEMPI_FILE%
if exist %TEMPO_FILE% del %TEMPO_FILE%
endlocal
echo.
exit /b 1

@rem 日付のフォーマットを/から-に変える。ファイルサイズを3桁区切りにする。
@rem %4は無くてもいいが、同じバッチファイルを再利用するため4番目のパラメーターを使用する。
:FORMAT
setlocal enabledelayedexpansion

@rem echo %0 %1 %2 %3 %4
set fdatetime=%1
set file=%2
set len=%3
set fdatetime=!fdatetime:/=-!
if exist %~dp0PrintNum3.bat (
  for /F "usebackq" %%n in (`%~dp0PrintNum3.bat !len!`) do set len=%%n
)
rem echo !fdatetime!+!file!+"!len!"
echo !fdatetime!+!file!+"!len!">> %4

endlocal
exit /b 0


:DONE
if exist %TEMPI_FILE% del %TEMPI_FILE%
if exist %TEMPO_FILE% del %TEMPO_FILE%
endlocal
echo.

EXIT /B 0

:DONE
if exist %TEMPI_FILE% del %TEMPI_FILE%
if exist %TEMPO_FILE% del %TEMPO_FILE%
endlocal
echo.

EXIT /B 0

PrintNum3.bat

@echo off
if "%1" == "" (
  echo 0
  exit /b
)

setlocal enabledelayedexpansion
set num=%1

set /a len=0
set num_t=%num%
:LEN_LOOP
if not "%num_t%" == "" (
  set num_t=%num_t:~1%
  set /a len=%len%+1
  goto :LEN_LOOP
)

set /a top_len=%len%%%3

set num3=%num:~-3,3%

if %len% gtr 3 (
  FOR /L %%i IN (6,3,%len%) DO call set num3=%%num:~-%%i,3%%,!num3!
  if %top_len% gtr 0 ( 
    call set num3=%%num:~0,%top_len%%%,!num3!
  )
)

echo %num3%

endlocal
exit /b

qsort.bat、qsort2.bat

DeleteOldFile.bat内でsort.exeを呼ぶようにしたので削除