3

I am using 7-zip to backup folders on my disk into 7z archives on a network storage. Each time the backup script runs, it will update the existing archives in 7-zip update mode (compress new files from disk and copy unchanged files from the old archive). It works fine but involves two complete transfers of each archive over the network.

Now, often the folder content has not changed at all since the last backup job, so it would be much more efficient to just skip the entire operation and leave the old archive as it is. How can I achieve this?

2
  • Which OS are you running? – Karan Apr 20 '15 at 10:40
  • It's Windows 7 x64. – Theo Tiger Apr 20 '15 at 12:59
2

Adding the "-stl" option sets the archives date/time to that of the last modified file. I made a test archive read-only, and got no error from 7zip when I "updated" when no files were changed. Caveat: When the "-mhe=on" option is used too, then the content of the archive is changed, but only when the update does not occur in the same minute as the previous update. In other words the "-mhe=on" always re-encrypts and re-stores headers and apparently uses the current time in minutes for that.

1

According to the manual, you should be able to specify a combination of state and action with the -u switch to precisely control in what cases you want the archive to be updated:

1

As an example demonstrates, 7z u c:\1\exist.7z -up0q3x2z0!c:\1\update.7z * -ms=off creates a new archive update.7z and writes to this archive all files from the current directory which differ from files in the exist.7z archive. If you omit the ! followed by the new archive name, then only the base or existing archive should get updated if the specified conditions are met.

5
  • Thank you for your answer. That's all ok so far, but my problem is that even if no file was changed 7z still creates an update.7z, or, in my case, will update the exist.7z in-place. I would like to have 7z recognize that no file was changed and that there is thus no need to touch the exist.7z at all. Now, it produces massive network traffic (complete down- and re-upload of all the exist.7z's) and makes the backup job unnecessary slow. – Theo Tiger Apr 20 '15 at 13:08
  • Does something like 7z u Exist.7z -u- -up0q0r2w2x0y2z0!Update.7z * not help? – Karan Apr 20 '15 at 17:47
  • Unfortunately not: 7z still creates the Update.7z although no file was changed. – Theo Tiger Apr 21 '15 at 10:54
  • But with -u- Exist.7z should be untouched. Moreover with the command I gave above Update.7z ought to have nothing inside but new/changed files. If it has files that are in Exist.7z then clearly the corresponding files on disk have either been updated or had their modified time changed. – Karan Apr 21 '15 at 14:23
  • Yes you are right, but this would be incremental backup style. I prefer to have a single-file backup for this purpose. So, maybe I could do this in two steps: create an Update.7z with changed files only (as you described) and then merge Exist.7z and Update.7z. I am not sure how complicated that would be, I have to check the manual first. – Theo Tiger Apr 22 '15 at 8:44
0

I extended Karan's answer, while preserving the backup archive last modified time

Windows batch is very limited, and I only could make this script work by using NirCmd - Windows command line tool

So this is a batch script that uses 7-zip and NirCmd to create backup archives or update them only if source directory was changed, while preserving the archive modified time, to prevent other programs from detecting the archive as changed, thus preventing unwanted uploads..

@ECHO OFF


SET BaseDir=c:\Users
SET BkpsDir=d:\Backup


IF NOT EXIST "7za.exe" GOTO ExitError
IF NOT EXIST "nircmd.exe" GOTO ExitError
SET TimeFile=%temp%\tmpCloneFileTimeFile.bkp
SET OutputFile=%temp%\tmpOutputFile.bkp

REM create a temporary file
copy /y NUL "%TimeFile%" 1>NUL


CALL :CompressDirIfChanged Public\Music PublicMusic.7z
CALL :CompressDirIfChanged Dragos\Favorites DragosFavorites.7z


DEL "%TimeFile%" /F /Q >nul 2>nul
DEL "%OutputFile%" /F /Q >nul 2>nul

ECHO.
ECHO SUCCESS
ECHO.
PAUSE
EXIT
goto:eof 


REM call :CompressDirIfChanged sourceDirRelativeToBaseDir ArchiveName
:CompressDirIfChanged
    SET BkpSrc="%~1"
    SET ArchDest=%BkpsDir%\%~2
    CD "%BaseDir%"
    IF EXIST "%ArchDest%" (
        nircmd.exe clonefiletime "%ArchDest%" "%TimeFile%"
        7za.exe u -up1q0r2x1y2z1w2 -mx=9 "%ArchDest%" "%BkpSrc%" 1>"%OutputFile%"
        IF errorlevel 1 GOTO ExitError
        FINDSTR /bli /c:"Items to compress: 0" "%OutputFile%" && FINDSTR /bli /c:"Files read from disk: 0" "%OutputFile%" && (
            ECHO - no changes in %BkpSrc%, restoring Last Modified Time
            nircmd.exe clonefiletime "%TimeFile%" "%ArchDest%"
        ) || (
            ECHO - updating %ArchDest%
        )
    ) ELSE (
        ECHO - creating %ArchDest%
        7za.exe a -aoa -mx=9 "%ArchDest%" "%BkpSrc%" 1>nul
        IF errorlevel 1 GOTO ExitError
    )
goto:eof

:ExitError
    ECHO ERROR!
    PAUSE
    EXIT 1
goto:eof

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.