0

Based on files LastWriteTime property my script create a table 'File Age' with a custom output. The script work fine, my problem is with the output of a specific column 'Age' that i'cant set the order like i will. I already try to use cmdlet "Sort-Object -descending" but without success,data is randomly positioned. Maybe there is another way to customize that?

My desired output look like that:

    Age
1 Day - 1 Week
1 Week - 1 Month
1 Month - 6 Months
6 Months - 1 Year
1 Year - 2 Years
< 2 Years

Here is my script:

$scan = gci c:\MyFolder
$scan | Add-Member ScriptProperty -Name FileAgeDays -Value {
            [int]((Get-Date) - ($this.LastWriteTime)).TotalDays}
$scan | Add-Member ScriptProperty -Name FileAge -Value {   

if ($this.FileAgeDays -le 7) {
    "1 Day - 1 Week"
}
elseif ($this.FileAgeDays -ge 7 -and $this.FileAgeDays -le 30) {
    "1 Week - 1 Month"
}
elseif ($this.FileAgeDays -ge 30 -and $this.FileAgeDays -le 180) {
    "1 Month - 6 Months"
}
elseif ($this.FileAgeDays -ge 180 -and $this.FileAgeDays -le 365) {
    "6 Months - 1 Year"
}
elseif ($this.FileAgeDays -ge 365 -and $this.FileAgeDays -le 730) {
    "1 Year - 2 Years"
}
elseif ($this.FileAgeDays -ge 730) {
    "< 2 Years"
}
}
$grp = $scan | ?{ ! $_.PSIsContainer } | Group FileAge | 
           Add-Member -MemberType ScriptProperty -Name SizeMB -Value {
           ($this.Group | Measure-Object Length -sum).Sum / 1MB} -PassThru

$age_frag = $grp | select`
 @{l='Size (MB)';e={"{0:n}" -f ($_.sizemb)}},`
 @{l='Age';e={$_.name}}, Count|
ConvertTo-Html -Fragment -As Table -PreContent "<br><H2><a name=a009>File Age</a></H2>"| 
Out-String

Any help will be welcome.

1 Answer 1

2

You could use a switch to replace the text-value with sortable data, ex. an integer.

Sample data:

$data = [pscustomobject]@{ ID=1; FileAge="1 Day - 1 Week"},
[pscustomobject]@{ ID=4; FileAge="6 Months - 1 Year"},
[pscustomobject]@{ ID=2; FileAge="1 Week - 1 Month"},
[pscustomobject]@{ ID=5; FileAge="1 Year - 2 Years"},
[pscustomobject]@{ ID=6; FileAge="< 2 Years"},
[pscustomobject]@{ ID=3; FileAge="1 Month - 6 Months"}

$data

ID FileAge           
-- -------           
 1 1 Day - 1 Week    
 4 6 Months - 1 Year 
 2 1 Week - 1 Month  
 5 1 Year - 2 Years  
 6 < 2 Years         
 3 1 Month - 6 Months

Now, let's sort it:

$data | Sort-Object {
    switch($_.FileAge) {
    "1 Day - 1 Week" { 1 }
    "1 Week - 1 Month" { 2 }
    "1 Month - 6 Months" { 3 }
    "6 Months - 1 Year" { 4 }
    "1 Year - 2 Years" { 5 }
    "< 2 Years" { 6 }
    }
}

ID FileAge           
-- -------           
 1 1 Day - 1 Week    
 2 1 Week - 1 Month  
 3 1 Month - 6 Months
 4 6 Months - 1 Year 
 5 1 Year - 2 Years  
 6 < 2 Years 

Personally, I would design the script differently. I would have added a FileAgeGroup-property with integer-values like 1,2,3.., sorted by that and then used Select-Object to genereate the user-friendly output:

$data | Sort-Object ID | Select-Object @{n="FileAgeName";e={
    switch($_.ID) {
    1 { "1 Day - 1 Week" }
    2 { "1 Week - 1 Month" }
    3 { "1 Month - 6 Months" }
    4 { "6 Months - 1 Year" }
    5 { "1 Year - 2 Years" }
    6 { "< 2 Years" }
    }
}}

FileAgeName
-----------
1 Day - 1 Week
1 Week - 1 Month  
1 Month - 6 Months
6 Months - 1 Year 
1 Year - 2 Years  
< 2 Years

UPDATE: Here's an untested, modified version of your sample where my first solution implemented (sorting only without rewriting your code). I've added comments above the added code.

$scan = gci c:\MyFolder
$scan | Add-Member ScriptProperty -Name FileAgeDays -Value {
            [int]((Get-Date) - ($this.LastWriteTime)).TotalDays}
$scan | Add-Member ScriptProperty -Name FileAge -Value {   

if ($this.FileAgeDays -le 7) {
    "1 Day - 1 Week"
}
elseif ($this.FileAgeDays -ge 7 -and $this.FileAgeDays -le 30) {
    "1 Week - 1 Month"
}
elseif ($this.FileAgeDays -ge 30 -and $this.FileAgeDays -le 180) {
    "1 Month - 6 Months"
}
elseif ($this.FileAgeDays -ge 180 -and $this.FileAgeDays -le 365) {
    "6 Months - 1 Year"
}
elseif ($this.FileAgeDays -ge 365 -and $this.FileAgeDays -le 730) {
    "1 Year - 2 Years"
}
elseif ($this.FileAgeDays -ge 730) {
    "< 2 Years"
}
}
$grp = $scan | ?{ ! $_.PSIsContainer } | Group FileAge | 
           Add-Member -MemberType ScriptProperty -Name SizeMB -Value {
           ($this.Group | Measure-Object Length -sum).Sum / 1MB} -PassThru

#Scriptblock that can be used to sort by FileAge (Name-property in a Group)
$fileageSorting = {
    switch($_.Name) {
    "1 Day - 1 Week" { 1 }
    "1 Week - 1 Month" { 2 }
    "1 Month - 6 Months" { 3 }
    "6 Months - 1 Year" { 4 }
    "1 Year - 2 Years" { 5 }
    "< 2 Years" { 6 }
    }
}

$age_frag = $grp |
#Sorting
Sort-Object $fileageSorting |
select @{l='Size (MB)';e={"{0:n}" -f ($_.sizemb)}}, @{l='Age';e={$_.name}}, Count |
ConvertTo-Html -Fragment -As Table -PreContent "<br><H2><a name=a009>File Age</a></H2>"| 
Out-String
Sign up to request clarification or add additional context in comments.

1 Comment

Hello Frode Thank you very much for your replay, but i don't understand how i could implement it in my main script? How can i set it in my if loop?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.