functions/Show-FolderUsageAge.ps1

Function Show-FolderUsageAge {
    [cmdletbinding(DefaultParameterSetName = '__AllParameterSets')]
    [alias('sfa')]
    [OutputType("FileAging","None")]
    Param(
        [Parameter(
            Position = 0,
            Mandatory,
            ValueFromPipelineByPropertyName,
            HelpMessage = 'Specify the path to the folder to analyze. Use a full file system path')]
        [ValidateNotNullOrEmpty()]
        [string]$Path,

        [Parameter(HelpMessage = "Specify the file aging property. Default is 'LastWriteTime'.")]
        [ValidateSet('LastWriteTime', 'CreationTime')]
        [string]$Property = 'LastWriteTime',

        [Parameter(HelpMessage = 'Display raw output without formatting.')]
        [switch]$Raw
    )
    DynamicParam {
        If ($isWindows -OR ($PSEdition -eq 'Desktop')) {
            $paramDictionary = New-Object -Type System.Management.Automation.RuntimeDefinedParameterDictionary

            #Computername
            $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
            $attributes = New-Object System.Management.Automation.ParameterAttribute
            $attributes.ParameterSetName = 'Windows'
            $attributes.ValueFromPipeline = $true
            $attributes.ValueFromPipelineByPropertyName = $True
            $attributes.HelpMessage = 'Specify the name of a remote computer. You must have admin rights. The default is the localhost.'

            $v = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute
            $AttributeCollection.Add($v)
            $attributeCollection.Add($attributes)

            $dynAlias = New-Object System.Management.Automation.AliasAttribute -ArgumentList 'CN'
            $attributeCollection.Add($dynAlias)

            $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter('ComputerName', [String[]], $attributeCollection)
            $dynParam1.Value = '$env:Computername'
            $paramDictionary.Add('ComputerName', $dynParam1)

            #credential
            $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
            $attributes = New-Object System.Management.Automation.ParameterAttribute
            $attributes.ParameterSetName = 'Windows'
            $attributes.ValueFromPipelineByPropertyName = $True
            $attributes.HelpMessage = 'specify an alternate credential'

            $v = New-Object System.Management.Automation.ValidateNotNullOrEmptyAttribute
            $AttributeCollection.Add($v)
            $attributeCollection.Add($attributes)

            $dynAlias = New-Object System.Management.Automation.AliasAttribute -ArgumentList 'RunAs'
            $attributeCollection.Add($dynAlias)

            $dynParam1 = New-Object -Type System.Management.Automation.RuntimeDefinedParameter('Credential', [PSCredential], $attributeCollection)
            $paramDictionary.Add('Credential', $dynParam1)

            return $paramDictionary
        } # end if
    } #end DynamicParam

    Begin {
        $PSDefaultParameterValues['_verbose:Command'] = $MyInvocation.MyCommand
        $PSDefaultParameterValues['_verbose:block'] = 'Begin'
        _verbose -message $strings.Starting
        Write-Information $MyInvocation -Tags runtime
        if ($MyInvocation.CommandOrigin -eq 'Runspace') {
            $platformOS = If ($PSVersionTable.OS) {
                $PSVersionTable.OS
            }
            else {
                'Windows'
            }

            #Hide this metadata when the command is called from another command
            _verbose -message ($strings.PSVersion -f $PSVersionTable.PSVersion)
            _verbose -message ($strings.UsingHost -f $host.Name)
            _verbose -message ($strings.UsingOS -f $platformOS)
            _verbose -message ($strings.UsingModule -f $DiskReportingModule)
        }

        $sym = ' '
        $sb = {
            Param($Path, $Property, $Warning)

            Try {
                #validate the path
                $test = Get-Item -Path $path -ErrorAction Stop
                $Path = Convert-Path $Path
                $files = Get-ChildItem -Path $path -File -Recurse -ErrorAction Stop
                $now = Get-Date
            }
            Catch {
                $_
            }
            If ($files) {
                #initialize
                $Total2yr = 0
                $Total90 = 0
                $Total6mo = 0
                $Total1yr = 0
                $Total30 = 0
                $Total7 = 0
                $TotalCurrent = 0
                $2yrs = 0
                $1yr = 0
                $6mo = 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
                    $age = (New-TimeSpan -Start $file.$Property -End $now).Days
                    $count = $count + 1
                    Write-Progress -Activity 'File Aging Report' -Status 'Processing files in folder' -CurrentOperation $file.DirectoryName
                    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 180 } { $6mo = $6mo + 1; $Total6mo = $Total6mo + $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 }
                    }
                }
                Write-Progress -Activity 'File Aging Report' -Completed -Status "Processed $count files."
                $grandTotal = ($files | Measure-Object -Property Length -Sum).Sum

                $buckets = @()
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '2Yrs'
                    Count      = $2yrs
                    Size       = $Total2yr
                    PctTotal   = ($Total2yr / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '1Yrs'
                    Count      = $1yr
                    Size       = $Total1yr
                    PctTotal   = ($Total1yr / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '6Mo'
                    Count      = $6mo
                    Size       = $Total6mo
                    PctTotal   = ($Total6mo / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '3Mo'
                    Count      = $3mo
                    Size       = $Total90
                    PctTotal   = ($Total90 / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '1Mo'
                    Count      = $1mo
                    Size       = $Total30
                    PctTotal   = ($Total30 / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = '1Wk'
                    Count      = $1wk
                    Size       = $Total7
                    PctTotal   = ($Total7 / $grandTotal) * 100
                }
                $buckets += [PSCustomObject]@{
                    PSTypeName = 'FileAgingGroup'
                    Name       = 'Current'
                    Count      = $current
                    Size       = $TotalCurrent
                    PctTotal   = ($TotalCurrent / $grandTotal) * 100
                }

                [PSCustomObject]@{
                    PSTypeName   = 'FileAging'
                    Path         = $Path
                    Property     = $Property
                    AgingGroups  = $buckets
                    TotalFiles   = $count
                    TotalSize    = $grandTotal
                    Computername = [System.Environment]::MachineName
                }
            } #if
            else {
                Write-Warning $Warning
            }
        }
        $icmSplat = @{
            ScriptBlock  = $sb
            ArgumentList = ''
            ErrorAction  = 'Stop'
        }
    } #begin

    Process {
        $PSDefaultParameterValues['_verbose:block'] = 'Process'

        $icmSplat['ArgumentList'] = @($Path, $Property, $strings.NoFiles)
        _verbose ($strings.DetectedParameterSet -f $PSCmdlet.ParameterSetName)
        Write-Information $PSBoundParameters -Tags runtime
        if ($PSCmdlet.ParameterSetName -eq 'Windows') {
            $Credential = $PSBoundParameters['Credential']
            If ($Credential) {
                _verbose ($strings.RunAs -f $Credential.UserName)
                $icmSplat['Credential'] = $Credential
            }
            $ComputerName = $PSBoundParameters['ComputerName']
        } #Windows
        else {
            $Computername = [System.Environment]::MachineName
        }

        #Process computers individually
        foreach ($Computer in $ComputerName) {
            _verbose ($strings.FolderUsage -f $Path, ($Computer.ToUpper()))
            if ($computer -ne [System.Environment]::MachineName) {
                #don't include the local computer name for Invoke-Command
                $icmSplat['ComputerName'] = $Computer
                $icmSplat['HideComputerName'] = $True
            }
            else {
                #make sure Computername has been removed
                $icmSplat.Remove('ComputerName')
                $icmSplat.Remove('HideComputerName')
            }
            Write-Information $icmSplat -Tags runtime
            Try {
                $data = Invoke-Command @icmSplat
            }
            Catch {
                Write-Information $_ -Tags error
                $_
            }
            If ($data) {
                Write-Information $data -Tags data
                #update type names
                $data.PSObject.Properties.Remove('RunspaceID')
                if ($Raw) {
                    $data.PSObject.TypeNames.Insert(0, 'FileAging')
                    $data.AgingGroups.foreach({ $_.PSObject.TypeNames.Insert(0, 'FileAgingGroup') })
                    $data
                }
                else {
                    #Format the graphical output
                    $Path = Convert-Path $data.Path
                    $header = "[$cnStyle{1}$reset] $pathStyle{0}$reset" -f (_toTitleCase $Path), $data[0].Computername
                    #this will be the output
                    $out = @"
 
$header
 
 
"@

                    #get the longest file count
                    [string]$maxCount = ($data.AgingGroups | Sort-Object Count | Select -Last 1 -ExpandProperty Count)
                    #this is the length of the longest aging group name
                    $maxLength = 7
                    foreach ($item in $data.AgingGroups) {
                        $pct = $item.PctTotal
                        [double]$scaled = $pct / 2
                        [int]$used = 50 - $scaled
                        $displayPct = [math]::Round($scaled * 2, 2)
                        $bar = ($sym * $scaled)
                        $remain = 50 - $scaled
                        #colors are defined as module-scoped variables
                        if ($pct -gt 50) {
                            $bgColor = $redBG
                            $fgColor = $red
                        }
                        elseif ($pct -gt 20) {
                            $bgColor = $yellowBG
                            $fgColor = $yellow
                        }
                        else {
                            $bgColor = $greenBG
                            $fgColor = $green
                        }
                        $fileCount = "$([char]27)[30m{0}" -f ([string]$item.count).PadRight($maxCount.Length)
                        $out += "{0} [{1} {7}{2}{3}{4}] {5}{6:P2} ({8:N2}KB){3}`n" -f ($item.Name).PadRight($maxLength), $bgColor, $bar, $reset, (' ' * $remain), $fgColor, ($pct / 100),$fileCount,$($item.Size/1KB)

                    } #foreach item

                    $out +="`n{0:N0} total files measuring {1:N2}MB" -f $data.TotalFiles, ($data.TotalSize / 1MB)
                    $out
                }
                 Clear-Variable -Name data
            }
        }# Foreach computer
    }#process

    End {
        $PSDefaultParameterValues['_verbose:block'] = 'End'
        $PSDefaultParameterValues['_verbose:Command'] = $MyInvocation.MyCommand
        _verbose $strings.Ending
        Write-Information $strings.Ending -Tags runtime
    } #end
}