Let's face it both applications and people are terrible at cleaning up after themselves. As a result, cleaning up file systems has to be one of the most common requests I have had to help organizations through in my career and it's not always the servers needing the cleanup. Workstations often need the cleanup far more than the servers do. Organizations often target the network share locations for cleanup because that is where they see direct costs associated with this unnecessary collection of files in the form of additional backup media and premature system replacement costs. Workstations though also have file system cleanup needs as well.
We covered removing aged user profiles yesterday. There is also a need though to clean up the profiles and other folders that are still in use. Items such as old Temp Files and System Mini Dumps can easily consume an entire hard drive.
Luckily, a good start on addressing both the server and workstation cleanup tasks can be done in the same script. This is because both have similar needs. Both tasks need a way of reporting and/or deleting files that match a specified file name pattern. They also both need a way of reporting and/or deleting files over a certain age that match a specified name pattern. Today's included script can actually address one or both problems in a single pass through the file system.
This script, filecleanup.vbs, was put together from a bunch of different sources over the years to address the various cleanup requests I had received.
Using the script is simple assuming you have a good grasp of VBScript's regular expressions. See http://msdn.microsoft.com/en-us/library/ms974570.aspx for a quick refresher if you need help constructing regular expressions.
Since most file cleanup searches tend to be focused on the extension of the file in question, the one operator you will use continually is the $ operator as it means the expression needs to appear at the end. For example, the expression ".tmp$" will only match files with an extension of .tmp; it would not match "name.tmp.txt" The script does allow for multiple expressions to be provided in the same operation. Simply delimit the different strings with a semicolon (;). For example, ".tmp$;.err$;.log$" would match any file with a .tmp, .err, or .log extension.
Command line syntax:
Cscript filecleanup.vbs -FOLDER <folder> [-PATTERN <regexpr>] [-DATEPATTERN <regexpr> -NUMDAYS <n>] [-DELETE]
If you have file types that you want removed regardless of age, simply construct a regular expression that matches their name and include it in the –PATTERN argument to the script. For example, if you had a folder named c:\files that you wanted to remove every .dmp and .tmp file from, the command line would be:
Cscript filecleanup.vbs -FOLDER c:\files -PATTERN .dmp$;.tmp$ -delete
If you have file types that you want removed only after they reach a certain age, simply construct a regular expression that matches their name and include it in the –DATEPATTERN argument to the script along with the number of days old at which you wish to remove them. For example, if you wish to remove all .log and .err files from the c:\files folder after 3 days the command line would be:
Cscript filecleanup.vbs -FOLDER c:\files -DATEPATTERN .log$;.err$ -NUMDAYS 3 -delete
The two previous examples can even be combined into a single action. If that were the case the command line would be:
Cscript filecleanup.vbs -FOLDER c:\files -PATTERN .dmp$;.tmp$ -DATEPATTERN .log$;.err$ -NUMDAYS 3 -delete
If you simply want a list of files that meet the criteria, but don't want to delete them, simply leave off the –delete argument and the script will simply report the names and their location.
What the script does not do is cleanup empty folders.
As one can imagine, this script can still be used for a number of very useful things such as:
- Cleaning up end user profiles of TMP files over a certain age
- Cleaning up transient network locations such as scan destinations
- Removing unwanted file types from network shares such as potentially .MP3, .WMA, WMV, etc.
- Removing unwanted application log, dump, or detail files from systems
on error resume next
Sub Usage()
WScript.Echo UCase(WScript.ScriptName) &_
" - Reports/Deletes files based on name and age" & vbNewLine & vbNewLine &_
"Enumerates files starting at a specified folder and evaluates there name and age against" & vbNewLine &_
"provided patterns and either reports them or optionally deletes them." & vbNewLine & vbNewLine &_
WScript.ScriptName & " -FOLDER <folder> [-PATTERN <regexpr>] [-DATEPATTERN <regexpr> -NUMDAYS <n>] [-DELETE]" & vbNewLine &_
"-FOLDER <folder> Start the search at the specified folder" & vbNewLine &_
"-PATTERN <regexpr> Semicolon delimited regular expressions denoting files that should be flagged regardless of age." & vbNewLine &_
"-DATEPATTERN <regexpr> Semicolon delimited regular expressions denoting files that should be flagged based on age." & vbNewLine &_
"-NUMDAYS <n> Number of days that should be used as the threshold for the date flagged files, default is 3650" & vbNewLine &_
"-DELETE Flagged files should be deleted as well as reported" & vbNewLine &_
"-?, -H Displays this help" & vbNewLine & vbNewLine
WScript.Quit
End Sub
sPattern = ""
sTmPattern=""
iNumDays = 3650
boolDelete = false
While i < WScript.Arguments.Count
Select Case Replace(UCase(WScript.Arguments.Item(i)),"/","-")
Case "-FOLDER":
i=i+1
objStartFolder=WScript.Arguments.Item(i)
Case "-PATTERN":
i=i+1
sPattern=WScript.Arguments.Item(i)
Case "-DATEPATTERN":
i=i+1
sTmPattern=WScript.Arguments.Item(i)
Case "-NUMDAYS":
i=i+1
iNumDays=clng(WScript.Arguments.Item(i))
case "-DELETE":
boolDelete = true
Case "-?":
usage()
Case else:
usage()
End Select
i = i + 1
wend
if len(objStartFolder) = 0 then
wscript.echo "Starting Folder not specified."
wscript.quit -1
end if
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(objStartFolder)
if err.number <> 0 then
wscript.echo "Starting Folder: " & objStartFolder & " is not accessible or does not exist."
wscript.quit -1
end if
' Wscript.Echo objFolder.Path
Set colFiles = objFolder.Files
For Each objFile in colFiles
boolMatch = false
if NameMatch(objFile.Name, sPattern) then
boolMatch = true
end if
if not boolMatch then
if NameMatch(objFile.Name, sTmPattern) then
DaysOldMod = Int(Now() - objFile.DateLastModified)
DaysOldCreate = Int(Now() - objFile.DateCreated)
if (DaysOldCreate > iNumDays) and (DaysOldMod > iNumDays) then
boolMatch = true
end if
end if
end if
if boolMatch then
Wscript.Echo objStartFolder & "\" & objFile.Name
if boolDelete then
objFSO.DeleteFile objStartFolder & "\" & objFile.Name, true
if err.number <> 0 then
wscript.echo "Unable to delete file: " & objStartFolder & "\" & objFile.Name
err.clear
end if
end if
end if
Next
' Wscript.Echo
ShowSubfolders objFSO.GetFolder(objStartFolder)
Sub ShowSubFolders(Folder)
For Each Subfolder in Folder.SubFolders
' Wscript.Echo Subfolder.Path
Set objFolder = objFSO.GetFolder(Subfolder.Path)
Set colFiles = objFolder.Files
For Each objFile in colFiles
boolMatch = false
if NameMatch(objFile.Name, sPattern) then
boolMatch = true
end if
if not boolMatch then
if NameMatch(objFile.Name, sTmPattern) then
DaysOldMod = Int(Now() - objFile.DateLastModified)
DaysOldCreate = Int(Now() - objFile.DateCreated)
if (DaysOldCreate > iNumDays) and (DaysOldMod > iNumDays) then
boolMatch = true
end if
end if
end if
if boolMatch then
Wscript.Echo Subfolder.Path & "\" & objFile.Name
if boolDelete then
objFSO.DeleteFile Subfolder.Path & "\" & objFile.Name, true
if err.number <> 0 then
wscript.echo "Unable to delete file: " & Subfolder.Path & "\" & objFile.Name
err.clear
end if
end if
end if
Next
' Wscript.Echo
ShowSubFolders Subfolder
Next
End Sub
function NameMatch(sName, sPattern)
NameMatch=false
if len(sPattern) = 0 then
exit function
end if
set re = new regexp
re.ignorecase=true
arrPattern = split(sPattern, ";")
for each pattern in arrPattern
re.pattern = pattern
if re.test(sName) then
NameMatch=true
exit function
end if
next
end function
No comments:
Post a Comment