06 Sep 2007
Deleting Old Files
I’ve had this script around for some time, and thought I would share it. There are many utilities that will do this, but this one is designed for VBScript, and uses regular expressions for the file pattern. This allows for almost surgical removal of files from a working folder or archive folder. I’ve used this script for some time on several servers I work with, and it’s pretty reliable.
You can also execute the script in the console (with CScript), and it will display a list of available parameters. Enjoy.
You can download the code here.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 | ' DeleteAgedFiles.vbs -- Remove files by any combination of timestamp aging, file pattern. ' John J Schultz -- 12/12/2005 -- Public Domain. ' ' //B is the switch recommended for production use with wscript to suppress operator messages from ' the script engine (e.g. when launched from a timer). Due to the number of WScript.Echo statements used, ' Cscript is highly recommended--even when testing. ' ---------------------------- ' Parameters Dim bAggressive Dim bTestRun Dim bIncludeSubFolders Dim bSpareRootFolder Dim bRemoveEmptyFolders Dim bBatchMode Dim bUserConfirmationForDelete Dim bIgnoreZeroLengthFiles Dim nDateToCheck Dim nDays Dim sStartFolder Dim sFilePattern Dim nPreserveFileCount ' ---------------------------- ' Global Dim dCutOff Dim iErr, sErr ' ################################################################################### ' Support Functions and Subs Sub LogAnEvent (iType, sMessage) Set WshShell = WScript.CreateObject("WScript.Shell") WshShell.LogEvent iType, sMessage Set WshShell = Nothing End Sub Function DateToAnsi (dTime) DateToAnsi = _ Year(dTime) & Right ("0" & Month (dTime), 2) & Right ("0" & Day (dTime), 2) & _ Hour(dTime) & Right ("0" & Minute (dTime), 2) & Right ("0" & Second (dTime), 2) End Function Sub QuickSort(ByRef aKey, nLowBound, nHighBound) ' Single dimension array only. Dim vPivot, nLowSwap, nHighSwap, vTemp If IsEmpty (nLowBound) Then nLowBound = LBound (aKey) End If If IsEmpty (nHighBound) Then nHighBound = UBound (aKey) End If ' Two items to sort If nHighBound - nLowBound = 1 Then If aKey(nLowBound) > aKey(nHighBound) Then vTemp = aKey(nLowBound) aKey(nLowBound) = aKey(nHighBound) aKey(nHighBound) = vTemp End If End If ' Three or more items to sort vPivot = aKey(int((nLowBound + nHighBound) / 2)) aKey(int((nLowBound + nHighBound) / 2)) = aKey(nLowBound) aKey(nLowBound) = vPivot nLowSwap = nLowBound + 1 nHighSwap = nHighBound Do ' Find the right nLowSwap While nLowSwap < nHighSwap and aKey(nLowSwap) <= vPivot nLowSwap = nLowSwap + 1 Wend ' Find the right nHighSwap While aKey(nHighSwap) > vPivot nHighSwap = nHighSwap - 1 Wend ' Swap values if out of sort order If nLowSwap < nHighSwap Then vTemp = aKey(nLowSwap) aKey(nLowSwap) = aKey(nHighSwap) aKey(nHighSwap) = vTemp End If Loop While nLowSwap < nHighSwap aKey(nLowBound) = aKey(nHighSwap) aKey(nHighSwap) = vPivot ' Recursive call ' 2 or more items in first section If nLowBound < (nHighSwap - 1) Then Call QuickSort(aKey, nLowBound, nHighSwap - 1) ' 2 or more items in second section If nHighSwap + 1 < nHighBound Then Call QuickSort(aKey, nHighSwap + 1, nHighBound) End Sub Function FolderExists (sFolderName) Dim oFS Set oFS = CreateObject("Scripting.FileSystemObject") FolderExists = oFS.FolderExists(sFolderName) set oFS = Nothing End Function Function FileMatchesPattern (sFile, sPattern, bIgnoreCase) ' Returns true if the file name matches the regular expression in sPattern. Dim oRegEx Set oRegEx = New RegExp With oRegEx .Pattern = sPattern .IgnoreCase = bIgnoreCase FileMatchesPattern = .Test (sFile) ' Execute search. End With Set oRegEx = Nothing End Function Sub RemoveFilesInFolder (sPath, bAtTop) ' Recursive -- uses modular variables Dim objFSO Dim objFolder Dim objFolders Dim objFile Dim objFiles Dim objItem Dim sFileName Dim bPardoned Dim sWorkPath Dim iErr Dim aSort Set objFSO = CreateObject("Scripting.FileSystemObject") sWorkPath = sPath If Right (sWorkPath, 1) <> "\" Then sWorkPath = sWorkPath & "\" Set objFolder = objFSO.GetFolder(sPath) ' First recurse to any sub-folders, and remove files from them. If bIncludeSubFolders Then For Each objItem In objFolder.SubFolders Call RemoveFilesInFolder (sWorkPath & objItem.Name, False) Next 'objItem End If WScript.Echo WScript.Echo "--- " & sPath ' First, enumerate the files and delete them. If Not bAtTop Or Not bSpareRootFolder Then If objFolder.Files.Count - nPreserveFileCount > 0 Then ReDim aSort (objFolder.Files.Count - 1) nI = 0 For Each objItem in objFolder.Files If nDateToCheck = 0 Then aSort (nI) = DateToAnsi (objItem.DateCreated) & "\" & objItem.Name ElseIf nDateToCheck = 1 Then aSort (nI) = DateToAnsi (objItem.DateLastModified) & "\" & objItem.Name ElseIf nDateToCheck = 2 Then aSort (nI) = DateToAnsi (objItem.DateLastAccessed) & "\" & objItem.Name End If nI = nI + 1 Next Call QuickSort (aSort, Empty, Empty) For nI = 0 To UBound (aSort) - nPreserveFileCount sTmp = Split(aSort(nI), "\")(1) 'WScript.Echo sTmp Set objFile = objFSO.GetFile (sWorkPath & sTmp) If Not FileMatchesPattern (objFile.Name, sFilePattern, True) Then bPardoned = True 'WScript.Echo "Name does not match filter pattern: " & objFile.Name ElseIf bIgnoreZeroLengthFiles And objFile.Size = 0 Then bPardoned = True WScript.Echo "Ignoring null-length file: " & objFile.Name ElseIf Not bAggressive And (objFile.Attributes AND 7) <> 0 Then WScript.Echo "Attribute-protected file ignored: " & objFile.Name bPardoned = True ElseIf nDateToCheck = 0 And DateAdd ("d", 0, objFile.DateCreated) > dCutOff Then WScript.Echo "Young file kept: " & objFile.Name bPardoned = True ElseIf nDateToCheck = 1 And DateAdd ("d", 0, objFile.DateLastAccessed) > dCutOff Then WScript.Echo "Young file kept: " & objFile.Name bPardoned = True ElseIf nDateToCheck = 2 And DateAdd ("d", 0, objFile.DateLastModified > dCutOff) Then WScript.Echo "Young file kept: " & objFile.Name bPardoned = True ElseIf bTestRun Then WScript.Echo "Qualifies for deletion: " & objFile.Name bPardoned = True Else bPardoned = False End If If Not bPardoned Then Err.Clear sFileName = objFile.Name On Error Resume Next objFile.Delete iErr = Err.Number On Error Goto 0 If iErr = 0 Then WScript.Echo "Deleted: " & objFile.Name Else WScript.Echo "Could not delete: " & objFile.Name End If End If Set objFile = Nothing Next ' File End If End If ' Remove the folder if it is empty, and the option to remove empty folders has been selected. ' NOTE: We don't delete the folder if any files are detected in it--protected or not. If (Not bAtTop Or bSpareRootFolder) And bRemoveEmptyFolders Then bPardoned = False For Each objItem In objFolder.Files bPardoned = True Exit For Next For Each objItem In objFolder.SubFolders bPardoned = True Exit For Next If Not bPardoned Then Err.Clear On Error Resume Next objFolder.Delete iErr = Err.Number On Error Goto 0 If iErr = 0 Then WScript.Echo "Killed empty folder..." Else WScript.Echo "Empty folder survived (may contain hidden or system files)..." End If End If End If Set objItem = Nothing Set objFolder = Nothing Set objFSO = CreateObject("Scripting.FileSystemObject") End Sub Sub HandleError (iErr, sErr) If bBatchMode Then LogAnEvent 1, sMsg Else WScript.Echo sMsg End If End Sub Sub Usage () WScript.Echo "DeleteOldFiles.vbs -- Remove files older than a specified number of days from one or more folders. " WScript.Echo "John J Schultz -- 12/12/2005 -- Public Domain. " WScript.Echo " " WScript.Echo "cscript DeleteOldFiles.vbs [{switches}] {days} folder [pattern]" WScript.Echo " " WScript.Echo "- Days is the age (in days) of the file's time stamp, to remove the file. Default: 30 days " WScript.Echo "- Folder is an existing folder containing the files targeted for removal. " WScript.Echo "- pattern is a regular expression used to filter matching file names targeted for removal. If not present, all files are included." WScript.Echo " " WScript.Echo "-------------------------- Available switches --------------------------- " WScript.Echo "/t - test only (a.k.a. chicken run): shows files affected, but does not actually delete them." WScript.Echo "/a - aggressive: attempts to remove read-only files. " WScript.Echo "/s - recurse files in subdirectories. " WScript.Echo "/d - remove a sub-directory if it is empty after removing files (does not include the initial folder). " WScript.Echo "/b - run in batch mode (errors logged to NT Event Log) " WScript.Echo "/r - spares files in the initial (root) folder. Use with /s when only files in sub-folders " WScript.Echo " should be removed. If this switch is used without /s, it has no effect. " WScript.Echo "/0- - ignores files with zero-length. " WScript.Echo "/d:c[reate] - (default) uses creation date to measure age. Note: Creation date on a copied " WScript.Echo " file is the date it was copied (i.e.: it does not inherit the original file's " WScript.Echo " creation date). " WScript.Echo "/d:a[ccess] - uses last access date to measure age. " WScript.Echo "/d:m[odified] - uses last modified date to measure age. " WScript.Echo "/n:# - preserve a count of files. Leaves at least this number of the newest files in the folder." WScript.Echo "/l:n - Log to NT Event Log: n = chatter level: " WScript.Echo " 0 = single summary " WScript.Echo " 1 = start/completion " WScript.Echo " 2 = (1) and all failures " WScript.Echo " 3 = (2) and all successes " WScript.Echo " NOTE: NT Event logging is performed if /b (batch mode) is specified, otherwise messages " WScript.Echo " are directed to the console. " WScript.Echo "------------------------------------------------------------------------ " WScript.Echo " " WScript.Echo "//B is the switch recommended for production use with wscript to suppress operator messages from " WScript.Echo "the script engine (e.g. when launched from a timer). Due to the number of WScript.Echo statements used, " WScript.Echo "CScript is highly recommended--even when testing. " End Sub ' ################################################################################### ' MAIN ' Module Dim oFSO Dim oFolder Dim oFile Dim oArgs Dim nArgCnt Dim iCount Dim sApp Dim bValidParameters Dim sTmp Dim sMsg sApp = "DeleteOldFiles.vbs" bTestRun = False bIncludeSubFolders = False bRemoveEmptyFolders = False bBenchmark = False bUserConfirmationForDelete = False bIgnoreZeroLengthFiles = False bTestOnly = False nDateToCheck = 2 ' Default to date modified. nDays = -1 nPreserveFileCount = 0 sStartFolder = "" sFilePattern = "[.]+" bValidParameters = True Set oArgs = WScript.Arguments iCount = oArgs.Count If iCount = 0 Then bValidParameters = False End If If bValidParameters Then For iCount = 0 to oArgs.Count - 1 sTmp = LCase (LTrim (RTrim (oArgs(iCount)))) If Left (sTmp, 1) = "/" Then If sTmp = "/a" Then bAggressive = True ElseIf sTmp = "/t" Then bTestRun = True ElseIf sTmp = "/s" Then bIncludeSubFolders = True ElseIf sTmp = "/r" Then bSpareRootFolder = True ElseIf sTmp = "/d" Then bRemoveEmptyFolders = True ElseIf sTmp = "/b" Then bBatchMode = False ElseIf sTmp = "/q" Then bUserConfirmationForDelete = True ElseIf sTmp = "/0-" Then bIgnoreZeroLengthFiles = True ElseIf Left (sTmp & Space (4), 4) = "/d:c" Then nDateToCheck = 0 ElseIf Left (sTmp & Space (4), 4) = "/d:a" Then nDateToCheck = 1 ElseIf Left (sTmp & Space (4), 4) = "/d:m" Then nDateToCheck = 2 ElseIf Left (sTmp & Space (3), 3) = "/n:" Then nPreserveFileCount = Int (Mid (sTmp & Space (4), 4)) If nPreserveFileCount < 0 Then WScript.Echo "Invalid preserve count: " & nPreserveFileCount bValidParameters = False End If Else bValidParameters = False sMsg = "unrecognized switch: " & sTmp End If ElseIf nDays = -1 And Instr ("0123456789", Left (sTmp, 1)) > 0 Then on error resume next nDays = CInt (sTmp) on error goto 0 If nDays < 0 Then bValidParameters = False sMsg = "day count must be >= 0: " & sTmp End If ElseIf sStartFolder = "" Then sStartFolder = LTrim (RTrim (oArgs(iCount))) ElseIf sFilePattern = "[.]+" Then sFilePattern = LTrim (RTrim (oArgs(iCount))) Else bValidParameters = False sMsg = _ "Attempt to re-specify the folder: " & sTmp & vbCrLf & _ "Already set as: " & sStartFolder End If Next End If Set objArgs = Nothing If sStartFolder = "" Then sMsg = _ "No starting folder specified" bValidParameters = False End If If Not bValidParameters Then If bBatchMode Then LogAnEvent 1, sMsg Else WScript.Echo sMsg End If Call Usage() WScript.Quit (1) End If If nDays < 0 Then nDays = 30 dCutOff = DateAdd ("d", -nDays, Now ()) WScript.Echo "Removing files older than " & nDays & " days (cutoff time: " & dCutoff & ")" WScript.Echo "Expiration is evaluated on the " & Split ("creation|last access|last modification", "|")(nDateToCheck) & " timestamp." ' --- Processing starts here Call RemoveFilesInFolder (sStartFolder, True) WScript.Echo "Script completed" WScript.Quit(0) |
Leave a Comment
You must be logged in to post a comment.