windowsbatch-file7zipbackups

Batch file to archive a directory and delete older 7z archive


I've been using the following batch file to backup a certain directory on a Windows Server machine for a long time. The batch file is run by a Windows Scheduled Task every day at a certain time and it zips a specific folder to a backup location after deleting the oldest .7z file (7z = www.7-zip.org).

This way I only ever have the number of .7z files specified in BackupNr in my backup folder and I don't have to manually delete the oldest .7z file.

The problem is the "Set BackupNr=1" line. Using BackupNr=1 I always have TWO .7z archives in my backup folder after the batch file has run.

I can't figure out what I need to change so that only ONE archive is kept whenever the batch file runs. How can I fix this?

@echo off

:: The name of the backup file that will be created. It will use the current date as the file name.
@For /F "tokens=1,2,3,4 delims=/ " %%A in ('Date /t') do @(
    Set FileName=%%A%%B%%C%%D
)

:: The name of the folders where all the backup .zip and report files will be stored.
Set ArchiveFolder=D:\Backup\Manual\Archives
Set ReportFolder=D:\Backup\Manual\Reports

:: The name of the folder that will be backed up, i.e. the AppData folder.
Set FolderToBackup=C:\AppData

:: The number of .zip files and .txt reports to keep. Older archives will be deleted according to their age. This ensures we only keep the most recent X number of backups.
Set BackupNr=1

:: Delete oldest backup archives so we only keep the number of archives specified in "skip=".
echo.>> DeletedBackups.txt
date /t >> DeletedBackups.txt
echo.>> DeletedBackups.txt
echo These older backups were deleted:>> DeletedBackups.txt
for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ArchiveFolder%\*') do (
    echo %ArchiveFolder%\%%a%1>> DeletedBackups.txt
    del /f /q %ArchiveFolder%\%%a%1
)

echo.>> DeletedBackups.txt
echo These older reports were deleted:>> DeletedBackups.txt
for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ReportFolder%\*') do (
    echo %ReportFolder%\%%a%1>> DeletedBackups.txt
    del /f /q %ReportFolder%\%%a%1
)

echo Starting the backup: %DATE% %TIME% >> %ReportFolder%\%FileName%.txt

:: Adds all files to 7z archive using BCJ2 converter, LZMA with 8 MB dictionary for main output stream (s0), and LZMA with 512 KB dictionary for s1 and s2 output streams of BCJ2.
C:\PROGRA~1\7-Zip\7z.exe a -t7z %ArchiveFolder%\%FileName%.7z %FolderToBackup%\* -m0=BCJ2 -m1=LZMA:d23 -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3 >> %ReportFolder%\%FileName%.txt

echo Backup finished at: %DATE% %TIME% >> %ReportFolder%\%FileName%.txt

:: Write the backup Start and End times to the BackupInfo.csv file.
gawk -f BackupRecord.awk %ReportFolder%\%FileName%.txt >> %ReportFolder%\BackupReport.csv

:: Write the file size of the backup .zip file that was just created to the log file.
set size=0
call :filesize %ArchiveFolder%\%FileName%.7z
echo Backup archive file size: %size% bytes >> %ReportFolder%\%FileName%.txt

exit

:: set filesize of 1st argument in %size% variable, and return
:filesize
  set size=%~z1
  exit /b 0

Thanks.


Solution

  • The /b switch in the dir command uses no header nor summary. result is a plain list of archives, in this case orderer descending by creation time, the most recent first.

    The problem is the skip=%BackupNr% in

    for /F "skip=%BackupNr% delims=" %%a in ('dir /b /o-d %ReportFolder%\*') do (
      echo %ReportFolder%\%%a%1>> DeletedBackups.txt
      del /f /q %ReportFolder%\%%a%1
    )
    

    as skip the first line, so the delete command erases all archives EXCEPT the most recent.

    then you execute the backup, so a new file is added to the directory. Result, two files.

    If you want only the last one, you should first perform the backup and after the deletion, or remove the skip=%BackupNr% from the for command.