Batch script help?

We have a product that backs itself up every hour into a zipfile named timestamp.zip (but timestamp is some real gibberish number chain).

Is there a way to add logic to a batch file to find the newest zip file (we only want to keep one zip a week for backup purpopses on a seperate server) and copy that one off to a share?

Edits in bold, also I posted this on the MS script forum as it may be more appropriate, I think I'm going to need to make the leap from batch scripts to .vbs scripts here shortly.

Is this Windows, I suppose?

yes it's windows

I'm not well versed in the ways of batch files, but a PHP or Perl script would do well here. You could even execute it from a batch file

Do you know VBScript at least a little bit? No? You should.

Awhile ago I wrote a simple script to manage log files of our app here. There are two locations where the log files are kept -- on D: where they can be viewed online and on G: drive where they're archived for later. It's like a two-stage archival system. I move things from D: to G: as they get old and D: runs out of space, and I delete things from G: altogether when it, in turn, begins to fill up. There are configurable thresholds for disc space usage (say, I want 2GB to be freed up on D: after I run the script). The files age is calculated based on their last modification date.

Save this text as "something.vbs", modify share names accordingly, change the deployment lists with the proper name of your machines. Judging but what you're saying, you don't need two-stage treatment. You can delete stage 1 and leave only stage 2 perhaps, but I am leaving both in for you to take a look, maybe you can adopt that.

You can run the script on your own desktop box if you have remote access to the shares, but obviously it will run faster if ran locally on the machines where the log files are. Run it from command line like this: "cscript something.vbs".

Or just let me know your operational parameters (share/path names, hostnames etc) and I'll modify this for you.

' Begin cut-paste
DEBUG_MSGS = False
INFO_MSGS = True

SHARE_NAME_WORK = "live$"
SHARE_NAME_ARCH = "archive$"
SPACE_INFO_TOTAL = 0
SPACE_INFO_AVAIL = 1
MEGABYTES = 1048576
MAX_DAYS_DATE_DIFF_ARCH = 90
MAX_DAYS_DATE_DIFF_CUR = 30
DELIM = vbNewLine
MIN_FREE_SPACE_MB = 1800
MIN_FREE_SPACE_MB_ARCH = 2000
MODE_OLDER_THAN = "olderthan"
MODE_SPACE_LESS_THAN = "spacelessthan"

Set objDeployments = CreateObject("Scripting.Dictionary")
Set objFSO = CreateObject("Scripting.FileSystemObject")

'sMode = MODE_OLDER_THAN
sMode = MODE_SPACE_LESS_THAN
bCleanupArchive = True
bMoveCurrentToArchive = True
bCleanupCurrent = False

sMsg = ""
If sRegion = "NY" Then
objDeployments.Add "NY Prod", Array("newyorkmachine1", "newyorkmachine2", "newyorkmachine3", "newyorkmachine4")
ElseIf sRegion = "TK" Then
objDeployments.Add "TK Prod", Array("tokyomachine1", "tokyomachine1")
Else
' Nothing
sMsg = "Please select a region."
End If
sDeployment = "NY Prod"

sOutput = "" & vbNewLine
Dim iJ

For Each sDeployment In objDeployments.Keys
iJ = 0
sOutput = sOutput & sDeployment & vbNewLine
WScript.Echo " *** Deployment: " & sDeployment & " *** "
For Each sServerName In objDeployments.Item(sDeployment)
iJ = iJ + 1
If InStr(sServerName, "\\") <> 1 Then
sDrive = "\\" & sServerName
Else
sDrive = sServerName
End If
sWorkShare = sDrive + "\" + SHARE_NAME_WORK
sArchShare = sDrive & "\" & SHARE_NAME_ARCH
asSpaceInfo = GetDiskSpace(sWorkShare)
InfoMsg iJ & ". " & sDrive & ": " & CLng(asSpaceInfo(SPACE_INFO_TOTAL) / MEGABYTES) & _
"MB / " & CLng(asSpaceInfo(SPACE_INFO_AVAIL) / MEGABYTES) & "MB"

Select Case sMode
Case MODE_OLDER_THAN
' Delete files older than specified
' Stage one: cleanup old archived log files from etcorelogs$ if necessary
If bCleanupArchive Then
' sRes = GetFilesAndFoldersOlderThan(sWorkShare & "\logs", MAX_DAYS_DATE_DIFF_CUR)
asFilesAndFolders = GetFilesAndFoldersOlderThan(sArchShare, MAX_DAYS_DATE_DIFF_ARCH)
DeleteFilesAndFolders asFilesAndFolders
End If

' Stage two: cleanup old archived log files from etcorelogs$ if necessary
If bMoveCurrentToArchive Then
asFilesAndFolders = GetFilesAndFoldersOlderThan(sWorkShare & "\logs", MAX_DAYS_DATE_DIFF_CUR)
MoveFilesAndFolders sArchShare & "\", asFilesAndFolders
End If
Case MODE_SPACE_LESS_THAN
' Delete enough files to free up a specified amount of disc space
' Stage one: cleanup old archived log files from etcorelogs$ if necessary
If bCleanupArchive Then
' sRes = GetFilesAndFoldersOlderThan(sWorkShare & "\logs", MAX_DAYS_DATE_DIFF_CUR)
asFilesAndFolders = GetOldFilesTotalLargerThan(sArchShare, MIN_FREE_SPACE_MB_ARCH)
DeleteFilesAndFolders asFilesAndFolders
End If

' Stage two: cleanup old archived log files from etcorelogs$ if necessary
If bMoveCurrentToArchive Then
' asFilesAndFolders = GetFilesAndFoldersOlderThan(sWorkShare & "\logs", MAX_DAYS_DATE_DIFF_CUR)
asFilesAndFolders = GetOldFilesTotalLargerThan(sWorkShare & "\logs", MIN_FREE_SPACE_MB)
MoveFilesAndFolders sArchShare & "\", asFilesAndFolders

End If
End Select

InfoMsg ""
Next
Next

Function GetFilesAndFoldersOlderThan(sResource, iDays)
Dim asFilesAndFolders, objFolder, iDaysOlder, sRes

dNow = Now
sRes = ""
DebugMsg "Will process " & sResource & " to clean up files older than " & iDays & " days"
Set objFolder = objFSO.GetFolder(sResource)
For Each objSubFolder In objFolder.SubFolders
iDaysOlder = Abs(DateDiff("d", GetDateFromFileName(objSubFolder.Name), dNow))
If iDaysOlder > iDays Then
DebugMsg " X " & objSubFolder.Path & "(" & iDaysOlder & " days old)"
sRes = sRes & objSubFolder.Path & DELIM
Else
DebugMsg " " & objSubFolder.Path
End If
Next
For Each objFile In objFolder.Files
iDaysOlder = Abs(DateDiff("d", objFile.DateCreated, dNow))
If iDaysOlder > iDays Then
DebugMsg " X " & objFile.Path & "(" & iDaysOlder & " days old)"
sRes = sRes & objFile.Path & DELIM
Else
DebugMsg " " & objFile.Path
End If
Next
If sRes <> "" Then sRes = Left(sRes, Len(sRes) - Len(DELIM))
GetFilesAndFoldersOlderThan = Split(sRes, DELIM)
End Function

Function GetOldFilesTotalLargerThan(sResource, iMegs)
Dim asFilesAndFolders, objFolder, iDaysOlder, sRes, nAvailSpace, objDicFolderSizes
Dim objCurFolder, sCurSubFolder, iI, iJ

dNow = Now
sRes = ""
InfoMsg "Will process " & sResource & " to clean up " & iMegs & "MB"
Set objFolder = objFSO.GetFolder(sResource)
' Strip the resource down to share name
asResUNC = Split(objFolder.Path, "\")
sResUNC = "\\" & asResUNC(2) & "\" & asResUNC(3)
nAvailSpace = objFSO.GetDrive(sResUNC).AvailableSpace / MEGABYTES
Set objDicFolderSizes = CreateObject("Scripting.Dictionary")
' Get subfolders and their sizes
ReDim asNames(objFolder.SubFolders.Count - 1)
ReDim asSizes(objFolder.SubFolders.Count - 1)
iI = 0
sRes = ""
For Each objSubFolder In objFolder.SubFolders
' sCurSubFolder = GetDateFromFileName(objSubFolder.Name)
sCurSubFolder = objSubFolder.Name
DebugMsg iI & vbTab & sCurSubFolder
Set objCurFolder = objFSO.GetFolder(sResource & "\" & sCurSubFolder)
objDicFolderSizes.Add sCurSubFolder, (objCurFolder.Size / MEGABYTES)

asSizes(iI) = objCurFolder.Size
asNames(iI) = sCurSubFolder
iI = iI +1
Next
' Sort by name, ie.e by date considering the names are YYYYMMDD-*
For iI = 0 To UBound(asNames)
For iJ = iI To UBound(asNames)
If asNames(iJ) < asNames(iI) Then
sTmp = asNames(iJ)
asNames(iJ) = asNames(iI)
asNames(iI) = sTmp
End If
Next
Next
InfoMsg vbNewLine & "Avail Space : " & nAvailSpace & " Needed: at least " & iMegs
DebugMsg vbNewLine & "Sorted: " & vbNewLine & "======="
iI = 0
While nAvailSpace < iMegs And iI < UBound(asNames)
sTmp = asNames(iI)
nAvailSpace = nAvailSpace + objDicFolderSizes.Item(sTmp)
DebugMsg sTmp & vbTab & "Size " & objDicFolderSizes.Item(sTmp) & vbTab & " After deletion: " & nAvailSpace
sRes = sRes & sResource & "\" & sTmp & DELIM
iI = iI + 1
Wend
If sRes <> "" Then sRes = Left(sRes, Len(sRes) - Len(DELIM))
If nAvailSpace >= iMegs Then
InfoMsg "Available space under " & sResource & " will be " & CLng(nAvailSpace) & "MB"
Else
InfoMsg "Could prepare cleanup of " & sResource & ", available space will be only " & nAvailSpace & "MB"
End If
GetOldFilesTotalLargerThan = Split(sRes, DELIM)
End Function

Function GetDiskSpace(sResource)
Dim objDrive, iTotal, iAvailable

Set objDrive = objFSO.GetDrive(sResource)
If Err Then
iTotal = -1
iAvailable = -1
Else
iTotal = objDrive.TotalSize
iAvailable = objDrive.AvailableSpace
End If
GetDiskSpace = Array(iTotal, iAvailable)
End Function

Function DeleteFilesAndFolders(asThem)
For Each sHim In asThem
If objFSO.FolderExists(sHim) Then
InfoMsg " will delete folder " & sHim
objFSO.DeleteFolder sHim, True ' Delete Read-Only subfolders/files as well
ElseIf objFSO.FileExists(sHim) Then
InfoMsg " will delete file " & sHim
objFSO.DeleteFile sHim, True ' Delete Read-Only files as well
End If
Next
End Function

Function MoveFilesAndFolders(sDest, asThem)
For Each sHim In asThem
If objFSO.FolderExists(sHim) Then
InfoMsg " will move folder " & sHim & " to " & sDest
objFSO.CopyFolder sHim, sDest
objFSO.DeleteFolder sHim, True
ElseIf objFSO.FileExists(sHim) Then
InfoMsg " will move file " & sHim & " to " & sDest
objFSO.CopyFile sHim, sDest
objFSO.DeleteFile sHim, True
End If
Next
End Function

Function GetDateFromFileName(sFileName)
sYear = Left(sFileName, 4)
sMonth = Mid(sFileName, 5, 2)
sDay = Mid(sFileName, 7, 2)

If IsNumeric(sYear) And IsNumeric(sMonth) And IsNumeric(sDay) Then
GetDateFromFileName = DateSerial(sYear, sMonth, sDay)
Else
GetDateFromFileName = DateValue(Now)
End If
End Function

Sub DebugMsg(sText)
If DEBUG_MSGS Then WScript.Echo sText
End Sub

Sub InfoMsg(sText)
If INFO_MSGS Then WScript.Echo sText
End Sub

I'm learning VBscript now, I've been reading the MS Scripting guide and I'm getting there but I'm still very green. I quit college because I realized that I didn't want to be a programmer but the background is helping now that I'm wading into the scripting world more and more so life is cyclical.

I'll play with what you've given me and ask for help if I start to realize I'm over my head.

Here's the code I manhandled together, I'm ashamed to say that it took me half the to hax0r this out.

It would be sweet to make it copy to a subdirectory under "..\wireless backup\YYYY-MM-DD" and then the files and not overwrite them but I'll work on that tomorrow.

Anyways, here's the code:

'***********************************************************************************
'*
'* Script File Name: WSC_BU.vbs
'* Created: 05/23/2006
'* Last Modified: 05/23/2006
'* Version: 1.0
'*
'* Main Function: Copies a backup zip and files to Vol02\configs
'*
'*
'*
'***********************************************************************************

Option Explicit 'forces the scripter to declare variables
On Error Resume Next 'When uncommented will let the script progress
'to the next line even when there are errors

'********************************************************************
'* Declare main variables
'* Dim is used to declare variables
'********************************************************************
Dim objFSO
Dim objFiles
Dim old
Dim oldfile
Dim File
Dim sfolder
Dim dfolder

'********************************************************************
'* Declare main constants
'* Const is used to declare constants
'********************************************************************
Const OverWriteFiles = True

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFiles = objFSO.Drives("C:").RootFolder.SubFolders("program files").SubFolders("nortel").SubFolders("wms").SubFolders("backup").SubFolders("auto").SubFolders("default").Files

objfso.deletefile("C:\Program Files\Nortel\WMS\log\default\backup.zip")

old = DateValue("01/01/1990")

For Each File In objFiles
If LCase(Right(File.Name, 4)) = ".zip" Then

If File.DateLastModified > old Then
Set OldFile = File
old = File.DateLastModified
End If
End If
Next

objfso.copyfile "C:\Program Files\Nortel\WMS\backup\auto\default\"&oldfile.name, "c:\Program Files\Nortel\WMS\log\Default\backup.zip"

sfolder = "C:\Program Files\Nortel\WMS\log\default"
dfolder = "\\vol02\workgroup\IS\Configs\Wireless Backup"
objfso.copyfolder sfolder, dfolder , OverWriteFiles