# Bat file to sum sizes of most recently created zip files



## folder (Dec 12, 2008)

Hi,
I'm trying to get a bat file that decides which kind of backup to do by comparing the sizes of the most recent full and differential backups.
This is what I am working with:
1) I store copies of my backups online. Due to my online storage provider's 2GB file size upload limit, I use Cobian Backup's ability to set a max size for each backup zip file so it automatically spans backups across multiple zip files. I end up with 5-10 2GB zip files for a full backup.
2) Cobian Backup names their backups the same way whether it is a full or differential backup. They advise using their log to tell which is which. The only way to tell which is which is to look at their the size, so I put fulls into a folder called Fulls and differentials into a folder called Diffs.
3) Cobian names the files "SourceFolder yyyy-MM-dd hh;mm;ss.zip" then the spanned files' extensions begin .z01, .z02, etc. with the same filename as the original.
I want the bat file to do differential backups until they reach 50% of the size of a full, then do a full instead. This is what I've go so far, but it only gets the size of one file into a variable so there's still a long way to go...

set filepath=c:\
set filename=testfile
set fileextension=.txt
dir /-c "%filepath%%filename%%fileextension%" | find "%filename%%fileextension%" > c:\temp.txt
for /f "tokens=1,2,3,4,5 delims= " %%i in ('type c:\temp.txt') do (set size=%%l)
echo The size of %filepath%%filename%%fileextension% is %size% bytes
pause
I have WIndows XP. Thank you for your help.


----------



## TheOutcaste (Aug 8, 2007)

Well, your example does a Dir of only one file name, so it will only get the size of that one filename.
Much easier to use the size modifier (*~z*, see *FOR /?*, at end) and let Dir and For do the work.
This will total the size of all files with the extension "fileextension" that are in "filepath", in this example, all *.txt* files in *C:\Test1*:


```
Setlocal EnableDelayedExpansion
Set filepath=c:\Test1
Set fileextension=.txt
Set size=0
For /f "usebackq tokens=*" %%I in (`Dir /B "%filepath%\*%Fileextension%"`) Do Set /A Size=!size!+%%~zI
echo The size of all %fileextension% files in %filepath% is %size% bytes
pause
```
HTH

Jerry


----------



## folder (Dec 12, 2008)

Thank you for your help!
I created the c:\test1 folder and put a .txt file into it. But I ran it, there seemed to be a problem with the %~zI variable. It gives the error "missing operand" after trying to run the Set command. I tried changing !size! to %size% but same error. 
I tried to echo %~zI to see what it was, but it gave this error _before_ the echo line:
The following usage of the path operator in batch-parameter
substitution is invalid: %~zI
For valid formats type CALL /? or FOR /?

Thanks again.


----------



## TheOutcaste (Aug 8, 2007)

folder said:


> * substitution is invalid: %~zI*


This usually indicates a typo. If you typed the code rather than copying it, make sure there are no missing % symbols around the variables.
For example, if you leave off the last % around fileextension, you'll get this:

```
C:\Test2>Set size=0
The following usage of the path operator in batch-parameter
substitution is invalid: %~zI


For valid formats type CALL /? or FOR /?

C:\Test1>For /f "usebackq tokens=*" %I in (`Dir /B "[COLOR=Red][B]c:\Test1\*%\*%Fileextension"[/B][/COLOR]`) Do Set /A Size=!size!+%%~zI
```
The part in red should display as c:\Test1\*.txt". One missing % can really change a command.
Also make sure you used back quotes (*`*) and not single quotes (*'*) around the Dir command, or it will give a missing operand error.

I just copied and pasted the code into a new file, saved it in C:
\test1 as getsize.cmd and it worked, so there doesn't _seem_ to be any typos in the code I posted.

Did find another bug though. Moved it to my scripts folder, and got a missing operator error. Forgot to test with the batch file in a different folder -- the size modifier doesn't seem to work if the current directory is not the same as the one you are checking, so I added the *pushd* and *popd* statements.

Add those two commands and double check the red characters, or copy and paste the following code and let's see if that works.
If you still get the error, replace the *Set /A size=!size!+%%~zI* part with just *Echo %%I* to see if it will list just the file name(s) and we'll go from there. Note that if the folder is empty, or has no files with that extension, it will also give a missing operand error, and will show the size as 0.


```
Setlocal EnableDelayedExpansion
Set filepath=c:\Test1
Set fileextension=.txt
[COLOR=Blue]PushD %filepath%[/COLOR]
Set size=0
For /F "usebackq tokens=*" %%I In ([COLOR=Red]`[/COLOR]Dir /B "[COLOR=Red]%[/COLOR]filepath[COLOR=Red]%[/COLOR]\*[COLOR=Red]%[/COLOR]Fileextension[COLOR=Red]%[/COLOR]"[COLOR=Red]`[/COLOR]) Do Set /A size=!size!+%%~zI
Echo The size of all %fileextension% files in %filepath% is %size% bytes
[COLOR=Blue]PopD[/COLOR]
pause
```
Jerry


----------



## folder (Dec 12, 2008)

Jerry, thanks, that worked beautifully. 
I went ahead and changed it to look for and add the sizes of files with the same filename but with * extensions, since it'll actually be adding the spanned zip backup files. I can handle the mathematical comparisons of sizes of full and differential backups, but can you tell me how to make the bat file differentiate out the most recent backup files from older ones in the same directory? (As I was saying above, those are the ones whose sizes I need to compare to decide whether to do a full or diff backup...and of course folder and filename structure etc is above too, if needed).
Thanks very much for your help.


----------



## TheOutcaste (Aug 8, 2007)

Several ways to do that, but it would be much much easier to archive the old backups to an archive folder every time you do a new Full backup. This way, the only files in the differential folder are for the most recent full backup, so there will be nothing to separate.
When you determine you need to make a new full backup, just have the script execute the following two lines:

*Move %backuppath%\Full\*.* %backuppath%\FullArchive
Move %backuppath%\Diff\*.* %backuppath%\DiffArchive*

then do the full backup. If you what to automate deleting of old backups, you would want to add a date to the archive folder, easiest to use the date the files were archived.

This shouldn't need to be done with the Online copies, just the local copies (I'm assuming you are checking the local copies with this batch script). If it needs to be done with the online copies as well, that will depend on how you can access them, via a Mapped drive, which would use the same methods as the local copy, or using FTP, which would require an FTP script to move the files.

If it is not possible to move the backups to an archive folder for some reason, it would be pretty easy to get the most recent full backup (do a dir with files sorted with newest last, last name is most recent full backup), then only check differential backup files that have the same or newer date.

Xcopy can do that easily. One problem though, Xcopy only looks at the _date_ when used in this manner, not the _time_, so if you create a new Full backup on the same date as an older Differential was done, that older Differential would be included with the new ones. You can code for that, but you would have to get the date _and_ time of the latest full backup, let Xcopy generate a list of the differential file names created on or after that same date, then get the date and time for those files, compare the date, and if the date is the same, compare the time, and exclude it from the list if necessary. Then you can use the list to get the file sizes.

Xcopy also looks at date modified, not date created. The backup program will have to access the Full backup file to determine which files to backup, but it _shouldn't_ be changing the modified date on the Full backup file, but if it does, then you'd have to parse the date/time from the file name, and use that to compare, a bit more complicated. Probably the best option if archiving the older backups can't be done, as using the file name would also catch the case where you accidentally do a differential backup based on an older Full backup.

With the file name in this form, *"SourceFolder yyyy-MM-dd hh;mm;ss.**", you'd need the following info to determine how to parse the date/time:
Will *SourceFolder* contain spaces, *-*, *;*, or *.* (other than the extension delimiter)?
Will the date and time format always be the same, i.e., a 4 digit year, and two digits (leading zeros where needed) for the rest?
Is the time shown in 12 or 24 hour format?

I believe archiving the local copies to a dated folder would be the easiest.

Jerry


----------



## folder (Dec 12, 2008)

Jerry,
Thanks for your help. I've been pretty busy lately so I haven't had a chance to get to this yet. I may be in good shape by clearing the directories and only having one set of backup files in each to add. I'll get down to it as soon as possible and let you know how it goes. Thanks again for all your help!


----------



## nilpo (Jun 29, 2004)

This would be much easier to accomplish using WSH.


----------

