'========================================================================== ' ' VBScript Source File -- Created with SAPIEN Technologies PrimalScript 2007 ' ' NAME: FileAgeReporter.vbs ' ' AUTHOR: Jeffery Hicks ' DATE : 7/5/2007 ' v1.1 7/5/2007 made owner information optional ' Changed filenames to use upper case ' v1.0 6/11/2007 original ' ' COMMENT: Analyze a folder and subfolders, getting file type utilization ' and file aging. A CSV file will be created with file information: ' File,Size,Date Created,Last Modified,Last Accessed,Extension,File Type,Owner ' ' A Summary report text file will also be created with analysis by ' file age and file type. ' ' Owner information is optional. The script runs a little slower if it ' has to get the owner for every file. ' ' The automatically generated filename will remove colons and replace \ with _ ' A timestamp will be appended so that checking a folder like c:\files\public ' will result in a file like c_files_public_20070611214328.csv ' ' You should be able to report on any local, mapped network drive or UNC path. ' ' You must run from a command prompt using CSCRIPT. ' USAGE: ' cscript FileAgeReporter /folder:folderpath [/norecurse] [/owner] [/verbose] [/?] ' ' THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY ' KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE ' IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A ' PARTICULAR PURPOSE. ' ' YOU MUST TEST IN A NON-PRODUCTION ENVIRONMENT '========================================================================== On Error Resume Next Const strVersion="1.1" strSyntax="cscript " & Wscript.ScriptName & " /folder:folderpath [/norecurse] [/owner] [/verbose] [/?]" Set objFSO=CreateObject("Scripting.FileSystemObject") Set objDict=CreateObject("Scripting.Dictionary") 'Only run from command line with CScript.exe if UCase(ChkEngine)="WSCRIPT.EXE" Then WScript.echo "You must run this from the command line using CScript." WScript.Quit End If 'display help if asked for. If WScript.Arguments.Named.Exists("?") Then Call ShowUsage() WScript.Quit End If 'User specified arguments If WScript.Arguments.named.Exists("folder") Then strFolder=WScript.Arguments.named("folder") 'Starting root folder 'verify folder exists If objFSO.FolderExists(strFolder)<>True Then WScript.Echo "Failed to find " & strFolder & ". Please verify the name and try again." WScript.quit End if Else WScript.Echo "Oops! Missing folder" Call ShowUsage() WScript.quit End If 'Default Values blnRecurse=True 'Recurse from starting directory blnVerbose=False 'If true, file information will be written 'to the console as it is analyzed blnOwner=False 'If true, file owner will be identified For 'each file if WScript.Arguments.named.Exists("verbose") Then blnVerbose=True if WScript.Arguments.named.Exists("norecurse") Then blnRecurse=False if WScript.Arguments.named.Exists("noowner") Then blnOwner=True 'filename will remove colons and replace \ with _ 'A timestamp will be appended so that checking a 'folder like c:\files\public will result in a file like 'C_FILES_PUBLIC_20070611214328.csv strFilename=Replace(strFolder,"\\","") 'strip off any leading \\ from a UNC strFileName=Replace(strFilename,":","") strFileName=Replace(strFilename,"\","_") strFileName=strFilename & "_" & GetLogTime strCSV=UCase(strFileName) & ".csv" 'file data CSV strReport=UCase(strFilename) & ".txt" 'file summary report iGrand=0 'initialize counter for grand count iGrandSize=0 'intialize counter for grand size dtNow=Now 'set variable with current timestamp for file aging calculations 'variables for aging counts and sizes i7=0 i30=0 i90=0 i180=0 i365=0 i730=0 iOld=0 i7size=0 i30size=0 i90size=0 i180size=0 i365size=0 i730size=0 iOldsize=0 Set objCSV=objFSO.CreateTextFile(strCSV,True) 'Only add owner information if specified If blnOwner Then objCSV.WriteLine "File,Size,Date Created,Last Modified,Last Accessed," &_ "Extension,File Type,Owner" Else objCSV.WriteLine "File,Size,Date Created,Last Modified,Last Accessed," &_ "Extension,File Type" End If Call ProcessFiles(strFolder) objCSV.Close Set objSummary=objFSO.CreateTextFile(strReport,True) objSummary.WriteLine "File Aging Summary for " & UCase(strFolder) objSummary.WriteLine "Report run " & dtNow objSummary.WriteLine String(Len("File Aging Summary for " & UCase(strFolder),"*")) objSummary.WriteLine VbCrLf objSummary.WriteLine "TOTALS:" 'summary results objSummary.WriteLine " Counted " & iGrand & " files in " & UCase(strFolder) objSummary.WriteLine " Total size " & FormatNumber((iGrandSize/1048576),2) &_ " MB (" & iGrandSize & " bytes)" objSummary.WriteLine VbCrLf objSummary.WriteLine "FILE AGING ANALYSIS:" objSummary.WriteLine "File Aging (based on last modified date)" objSummary.WriteLine " < 7 days" & vbTab & vbTab & "= " & i7 & " files " &_ FormatNumber((i7Size/1048576),2) & "MB (" & i7size & " bytes " & FormatPercent(i7/iGrand,2) & " of total)" objSummary.WriteLine " > 7 and < 30 days" & vbTab & "= " & i30 & " files " &_ FormatNumber((i30Size/1048576),2) & "MB (" & i30size & " bytes " & FormatPercent(i30/iGrand,2) & " of total)" objSummary.WriteLine " > 30 and < 90 days" & vbTab & "= " & i90 & " files " &_ FormatNumber((i90Size/1048576),2) & "MB (" & i90size & " bytes " & FormatPercent(i90/iGrand,2) & " of total)" objSummary.WriteLine " > 90 and < 180 days" & vbTab & "= " & i180 & " files " &_ FormatNumber((i180Size/1048576),2) & "MB (" & i180size & " bytes " & FormatPercent(i180/iGrand,2) & " of total)" objSummary.WriteLine " > 180 and < 1 yr" & vbTab & "= " & i365 & " files " &_ FormatNumber((i365Size/1048576),2) & "MB (" & i365size & " bytes " & FormatPercent(i365/iGrand,2) & " of total)" objSummary.WriteLine " > 1 yr and < 2 yrs" & vbTab & "= " & i730 & " files " &_ FormatNumber((i730Size/1048576),2) & "MB " & i730size & " bytes " & FormatPercent(i730/iGrand,2) & " of total)" objSummary.WriteLine " > 2 yrs" & vbTab & vbTab & "= " & iOld & " files " &_ FormatNumber((ioldSize/1048576),2) & "MB (" & iOldsize & " bytes " & FormatPercent(iOld/iGrand,2) & " of total)" objSummary.WriteLine VbCrLf objSummary.WriteLine "FILE TYPE ANALYSIS:" For Each item In objDict arrData=Split(objDict.Item(item),";") iName=arrData(0) iCount=arrData(1) iSize=arrData(2) iPercent=FormatPercent(iCount/iGrand,2) iPercentSize=FormatPercent(iSize/iGrandSize,2) objSummary.WriteLine item & " [" & iName & "] = " & iCount & " files (" & iPercent & " of total count)" objSummary.WriteLine vbTab & "Total Size = " & iSize & " bytes (" & iPercentSize & " of total size)" Next objSummary.Close WScript.Echo "See " & strCSV & " for file results." WScript.Echo "See " & strReport & " for analysis report." Sub ProcessFiles(strFolder) On Error Resume Next WScript.Echo "Analyzing: " & strFolder Set colFiles=objFSO.GetFolder(strFolder).Files For Each file In colFiles iGrand=iGrand+1 'increment grand total iGrandSize=iGrandSize+file.size strExt=UCase(objFSO.GetExtensionName(file)) 'file name is wrapped in "" in case there are any commas 'in the name or path strCSVData=Chr(34) & file & Chr(34) & "," & file.size & "," &_ file.DateCreated & "," & file.DateLastModified & ","&_ file.DateLastAccessed & "," & strExt & "," &_ file.Type If blnOwner Then strCSVData=strCSVData & "," & _ GetOwner(Replace(file,"\","\\")) If blnVerbose Then WScript.Echo strCSVData objCSV.WriteLine strCSVData If strExt="" Then strExt="NoExtension" 'Use dictionary to file extension data 'Key is extension, data is multi-valued: 'file.type,count,running total size If objDict.Exists(strExt) Then iTmp=objDict.Item(strExt) 'get current value objDict.Remove strExt 'remove current key arrTmp=Split(iTmp,";") 'item 0 is file type 'item 1 is count 'item 2 is size 're-add with incremented counts objDict.Add strExt,arrTmp(0) & ";" & arrTmp(1)+1 & ";" & arrTmp(2)+file.size Else objDict.Add strExt,File.Type & ";" & 1 & ";" & file.size End If 'Get Aging information iDiff=DateDiff("d",file.DateLastModified,dtNow) If iDiff < 7 Then i7=i7+1 i7size=i7Size+file.Size ElseIf iDiff <30 Then i30=i30+1 i30size=i30Size+file.Size ElseIf iDiff <90 Then i90=i90+1 i90size=i90Size+file.Size ElseIf iDiff <180 Then i180=i180+1 i180size=i180Size+file.Size ElseIf iDiff < 365 Then i365=i365+1 i365size=i365Size+file.Size ElseIf iDiff < 730 Then i730=i730+1 i730size=i730Size+file.Size Else iold=iold+1 ioldsize=ioldSize+file.Size End If Next 'recurse through subfolders If blnRecurse Then Set colFldrs=objFSO.GetFolder(strFolder).SubFolders For Each fldr In colFldrs Call ProcessFiles(fldr) Next End If End Sub Function GetLogTime() On Error Resume Next Dim strNow strNow = Now() GetLogTime = Year(strNow) _ & Pad(Month(strNow), 2, "0", True) _ & Pad(Day(strNow), 2, "0", True) _ & Pad(Hour(strNow), 2, "0", True) _ & Pad(Minute(strNow), 2, "0", True) _ & Pad(Second(strNow), 2, "0", True) End Function Function Pad(strText, nLen, strChar, bFront) Dim nStartLen If strChar = "" Then strChar = "0" End If nStartLen = Len(strText) If Len(strText) >= nLen Then Pad = strText Else If bFront Then Pad = String(nLen - Len(strText), strChar) _ & strText Else Pad = strText & String(nLen - Len(strText), _ strChar) End If End If End Function Function GetOwner(strFile) On Error Resume Next Dim objOwner Dim objWMIFile Dim objDescriptor strFileQuery="Select * from Win32_LogicalFileSecuritySetting WHERE Path='" & _ strFile & "'" Set oWmi=GetObject("winmgmts:") Set objWMIFile=oWMI.ExecQuery(strFileQuery) If IsNull(objWMIFile) Then GetOwner="Unavailable" Exit Function End If For Each item In objWMIFile r=item.GetSecurityDescriptor(objDescriptor) Set objOwner=objDescriptor.Owner If IsNull(objOwner.Name) Then strOwner="Unknown" Else strOwner=objOwner.name End If Next GetOwner=strOwner End Function Function ChkEngine() 'returns cscript.exe or wscript.exe strEngine=Wscript.FullName PosX=InStrRev(strEngine,"\",-1,vbTextCompare) ChkEngine=Mid(strEngine,PosX+1) End Function Sub ShowUsage() On Error Resume Next WScript.Echo vbCr WScript.Echo UCase(WScript.ScriptName) & " " & strVersion WScript.Echo String(Len(WScript.ScriptName),"_") Wscript.echo WScript.Echo "Usage: " WScript.Echo strSyntax Wscript.echo WScript.Echo "Example:" WScript.Echo WScript.ScriptName & " /folder:c:\scripts /owner" WScript.Echo VbCrLf WScript.Echo "The default setting is to recurse subfolders. You can " & vbcrlf &_ "override this by using /norecurse." Wscript.echo Wscript.echo "Owner information is optional. Use the /owner switch to capture" Wscript.echo "it. The script will run faster without if performance is an issue." Wscript.echo WScript.Echo "Use /verbose for more details about what the script is doing." WScript.Echo VbCrLf WScript.Echo WScript.ScriptName & " /? will display this help screen." End Sub