A few days ago, I posted an entry on how to run a file aging report using PowerShell. The script as written was pretty and all, but a little limiting. You really can’t do anything with the results. In many regards it is a VBScript rewritten for PowerShell (not that there’s anything wrong with that). But PowerShell can do so much more, especially when you think about piping objects between cmdlets. The original script just produces string output so you can’t do much else with it. What the script needs is a way to produce an object that can then be used by other PowerShell cmdlets. Thus was born FileAging2.ps1. I’ve attached the file as a text file so you don’t have to copy and paste from the blog entry.
The script is essentially the same as before. (I did update my formatting expressions per Jeffrey Snover’s suggestion about using 1MB instead of 1048576)
# FileAging2.ps1
# Jeffery Hicks SAPIEN Technologies, Inc.
# jhicks@sapien.com
# http://www.SAPIEN.com http://www.ScriptingAnswers.com
# http://sapien.eponym.com/blog
# This script developed and tested with PowerShell RTM
# !! TEST IN A NON-PRODUCTION ENVIRONMENT !!
Param($dir)
if ($dir -isnot [string]) {
Write-Host “ERROR: You must specify a directory path!” `
-foregroundcolor “RED” -backgroundcolor “Black”;`
return
}
$now=Get-Date
$files=Get-ChildItem -path $dir -recurse | `
where {($_.GetType()).name -eq “FileInfo”}
clear-host
#initialize
$Total2yr=0
$Total90=0
$Total1yr=0
$Total30=0
$Total7=0
$TotalCurrent=0
$2yrs=0
$1yr=0
$3mo=0
$1mo=0
$1wk=0
$current=0
$count=0
#enumerate files and get information
foreach ($file in $files) {
$age=($now.subtract(($file.LastWriteTime))).days
$count=$count+1
Write-Progress -Activity “File Aging Report” `
-status $file.DirectoryName -currentoperation $file.name
switch ($age) {
{$age -ge 730} {$2yrs=$2yrs+1;$Total2yr=$Total2Yr+$file.length;break}
{$age -ge 365} {$1yr=$1yr+1;$Total1yr=$Total1Yr+$file.length;break}
{$age -ge 90} {$3Mo=$3Mo+1;$Total90=$Total90+$file.length;break}
{$age -ge 30} {$1Mo=$1Mo+1;$Total30=$Total30+$file.length;break}
{$age -ge 7} {$1wk=$1wk+1;$Total7=$Total7+$file.length;break}
{$age -lt 7} {$current=$current+1;$TotalCurrent=$TotalCurrent+`
$file.Length;break}
}
}
#format file size totals to MB
$Total2yr=”{0:N2}” -f ($Total2yr/1MB)
$Total90=”{0:N2}” -f ($Total90/1MB)
$Total1yr=”{0:N2}” -f ($Total1yr/1MB)
$Total30=”{0:N2}” -f ($Total30/1MB)
$Total7=”{0:N2}” -f ($Total7/1MB)
$TotalCurrent=”{0:N2}” -f ($TotalCurrent/1MB)
#create new object to hold values
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “2Yrs”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $2yrs
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $Total2yr
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “1Yr”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $1yr
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $Total1yr
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “3Mo”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $3mo
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $Total90
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “1Mo”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $1mo
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $Total30
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “1Wk”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $1wk
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $Total7
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
$obj = New-Object System.Object
Add-Member -inputobject $obj -membertype NoteProperty -Name Age -value “Curr”
Add-Member -inputobject $obj -membertype NoteProperty -Name Count -value $current
Add-Member -inputobject $obj -membertype NoteProperty -Name MB -value $TotalCurrent
Add-Member -inputobject $obj -membertype NoteProperty -Name DirPath -value $dir.ToString()
Write-Output $obj
#EOF
The primary improvement to the script is using New-Object to create a generic .NET object and then calling Add-Member to populate the object with data. Write-Object sends the object data to PowerShell so it can present it. But that also means I have an object I can pipe to other cmdlets.
Here’s a screen shot of what I get when I run a the command:
.\fileaging2.ps1 s:\ | format-table -autosize
Or I could do something like:
.\fileaging2.ps1 s:\ | export-csv “c:\reports\S-age.csv”
and save the information to a csv file.
I can even take this a step further and use PowerGadget‘s out-chart cmdlet. I can run an expression like this:
.\fileaging2.ps1 s:\ | out-chart -values Count,MB -label Age -Title “File Aging Report: S:\” -floating -AllSeries_PointLabels_Visible True
and get something like this:
Or suppose I wanted a break down of files by age as a percentage of the total:
.\fileaging2.ps1 s:\out-chart -values Count -label Age -gallery pie -AllSeries_PointLabels_Visible True -galleryAttributes_LabelsInside -title “File Aging Report: S:\ (by count)” -floating
Once my script starts acting like an object, so many other possibilities present themselves. I’ve given up the string color coding that the original script had, but I believe “objectifying” the script more than covers the “loss.”
[Thanks to the folks at PowerGadgets for helping me get on the right track]
Great script!
Do you perhaps have a script that would not only count all the files by age, but actually create a listing of all those files (by age of course)?
I don’t have anything like that but you could take the current aging script and use it as a starting point. What you might try is building an array of file names for each aging bucket. You have to examine each file anyway so grabbing the name or full path should be a simple step to add.