How to use result of switch/if as property in Select-Object?

This topic contains 6 replies, has 3 voices, and was last updated by Profile photo of Rob Simmers Rob Simmers 1 year, 8 months ago.

  • Author
    Posts
  • #25402
    Profile photo of Alan B
    Alan B
    Participant

    I've got a number of directories to search that contain large files (backups) and small files (md5's).

    I've written a script that displays the files in a way that enables me to quickly validate the backups are current and there is an associated md5 for the backup.

    As a further script refinement I'd like to modify the file size display so rather than displaying the number of bytes in the large files the size is displayed as xx Gb, xx Mb, xx Kb as appropriate. In other words the value displayed in the file size column would be formatted differently depending on the size of the file.

    The following works to display file size in bytes, Kb, Mb, or Gb, depending which is selected, but is applied to all file sizes. I have been unable to create conditional logic to format the display dependent on file size.

    @{E={'{0,7:N0} bytes' -f ($_.Length)}}
    @{E={'{0,7:N0} Kb   ' -f ($_.Length/1kb)}}
    @{E={'{0,7:N0} Mb   ' -f ($_.Length)/1mb}}
    @{E={'{0,7:N0} Gb   ' -f ($_.Length/1gb)}}
    

    The current script is as follows. I believe I need to modify a Property of the Select-Object but have been unable to figure out how to make a conditional format property. Any help would be greatly appreciated.

    # Call this script from directory where backup files are being checked for current dates.
    # The script takes the 20 most recent spi and md5 files in the directory, groups them 
    # by drive and sorts in descending order by increment number and age
    #
    Get-ChildItem | `
     Where-Object {$_.name -like "*spi" -or $_.name -like "*md5"} | `
     Sort-Object LastWriteTime -Descending | `
     Select-Object -First 20 `
      -Property @{L='Drv';E={($_.Name.substring(0,1))}}, Name, LastWriteTime, @{L='Size';E={ '{0,14:N0}' -f ($_.Length)}} | `
     Sort-Object @{E='Drv'}, @{E={($_.Name.substring(12,$_.Name.Indexof(".")-12))};Descending=$true}, @{E='LastWriteTime';Descending=$true} | `
     ft -AutoSize -GroupBy Drv
    

    Sample output from the above script is below.

    PS G:\Backup2\Cust1\Dev1> G:\inspect_dir.ps1
    
       Drv: C
    
    Drv Name                       LastWriteTime         Size
    --- ----                       -------------         ----
    C   C_VOL-b003-i9107-cd.md5    5/19/2015 12:02:22 AM             59
    C   C_VOL-b003-i9107-cd.spi    5/18/2015 11:32:13 PM     99,440,640
    C   C_VOL-b003-i9060-cd.md5    5/18/2015 12:04:49 AM             59
    C   C_VOL-b003-i9060-cd.spi    5/17/2015 11:31:08 PM     98,367,488
    C   C_VOL-b003-i9013-cd-cw.md5 5/18/2015 12:04:10 AM             62
    C   C_VOL-b003-i9013-cd-cw.spi 5/16/2015 11:31:59 PM    125,943,296
    C   C_VOL-b003-i9013-cd.md5    5/18/2015 12:03:14 AM             59
    C   C_VOL-b003-i9013-cd.spi    5/16/2015 11:31:59 PM     98,432,000
    
       Drv: D
    
    Drv Name                       LastWriteTime         Size
    --- ----                       -------------         ----
    D   D_VOL-b003-i9104-cd.md5    5/19/2015 12:03:02 AM             59
    D   D_VOL-b003-i9104-cd.spi    5/18/2015 11:31:18 PM      5,874,688
    D   D_VOL-b003-i9057-cd.md5    5/18/2015 12:06:31 AM             59
    D   D_VOL-b003-i9057-cd.spi    5/17/2015 11:31:04 PM    158,806,528
    D   D_VOL-b003-i9010-cd-cw.md5 5/18/2015 12:05:56 AM             62
    D   D_VOL-b003-i9010-cd.md5    5/18/2015 12:05:24 AM             59
    
       Drv: E
    
    Drv Name                       LastWriteTime         Size
    --- ----                       -------------         ----
    E   E_VOL-b003-i9109-cd.md5    5/19/2015 12:02:41 AM             59
    E   E_VOL-b003-i9109-cd.spi    5/18/2015 11:30:34 PM      1,001,984
    E   E_VOL-b003-i9062-cd.md5    5/18/2015 12:05:11 AM             59
    E   E_VOL-b003-i9062-cd.spi    5/17/2015 11:30:31 PM      1,013,248
    E   E_VOL-b003-i9015-cd-cw.md5 5/18/2015 12:05:04 AM             62
    E   E_VOL-b003-i9015-cd.md5    5/18/2015 12:05:00 AM             59
    
  • #25405
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    First, a couple of general items, you don't need line continuation characters, Powershell see the pipe as a continuation and will ignore whitespace. Second, I don't know what your trying to parse here:

    @{E={($_.Name.substring(12,$_.Name.Indexof(".")-12))};Descending=$true}
    

    but I think you are going to have better luck setting it as a calculated property in your Select and then sorting on it. Next, I have two files in C:\ and "Size" is nothing right now:

       Drv: I
    
    Drv Name           LastWriteTime       Length Size          
    --- ----           -------------       ------ ----          
    I   IFRToolLog.txt 5/1/2015 4:46:31 PM   7788          7,788
    
    
       Drv: p
    
    Drv Name        LastWriteTime         Length Size          
    --- ----        -------------         ------ ----          
    p   pwruser.ini 4/16/2015 10:09:11 AM   4096          4,096
    
    

    I modified your code to look like this:

    Get-ChildItem C:\ -File |
    Select-Object -First 20 -Property @{L='Drv';E={($_.Name.substring(0,1))}},
                                      Name,
                                      LastWriteTime,
                                      Length, 
                                      @{L='Size';E={if ($_.Length -gt 5000){"Do GB"}else{"Do MB"} }} | 
    Sort-Object -Property @{Expression='Drv'; Ascending=$true }, @{Expression='LastWriteTime';Descending=$true} |
    ft -AutoSize -GroupBy Drv
    

    Note that in the Expression (E) that curly braces are executing code. In the curly braces I placed an if that if the length in bytes is bigger than 5000 to write a different message, but you could place a string format there to convert to MB/GB/TB or whatever. You can place try\catch, If, switch, etc. there since you are just executing a code block. Below you will see when this is executed that the first entry is "Do GB" because it is over 5000 bytes.

       Drv: I
    
    Drv Name           LastWriteTime       Length Size 
    --- ----           -------------       ------ ---- 
    I   IFRToolLog.txt 5/1/2015 4:46:31 PM   7788 Do GB
    
    
       Drv: p
    
    Drv Name        LastWriteTime         Length Size 
    --- ----        -------------         ------ ---- 
    p   pwruser.ini 4/16/2015 10:09:11 AM   4096 Do MB
    

    Not sure what or if there are "best practices" for what you put in those expressions for calculated properties, but I would keep them simple.

  • #25415
    Profile photo of Alan B
    Alan B
    Participant

    Rob, thanks for your reply. Will look through and see if I understand and can apply your suggestions.

    In regard to "...don't know what you're trying to parse..."

    The file names are auto generated by the backup with a fixed format. The last part includes a sequence # and indicator of the type of file. Type may be hourly, hourlies consolidated into dailies, dailies into weeklies and weeklies into monthlies. For whatever reason the the sequence number of a daily, weekly or monthly is the same as number used by the last file used to generate it. And, another mystery, the date time stamp of a consolidated file is not always later than the date time stamp of the files it is generated from.

    The parsing ensures the backup file and associated md5 are always grouped together in the output regardless of whether there are otherwise duplicate names or the time stamps are not in sequence with the sequence #.

    You can see an example of this in the name and time stamp output below

    C_VOL-b003-i9013-cd-cw.md5 5/18/2015 12:04:10 AM
    C_VOL-b003-i9013-cd-cw.spi 5/16/2015 11:31:59 PM
    C_VOL-b003-i9013-cd.md5    5/18/2015 12:03:14 AM
    C_VOL-b003-i9013-cd.spi    5/16/2015 11:31:59 PM
    
  • #25436
    Profile photo of Alan B
    Alan B
    Participant

    Here's my adaptation of what you've suggested Rob. It works, thank you. Thought I was doing this earlier but obviously not or it would have worked.

    Get-ChildItem | 
     Where-Object {$_.name -like "*spi" -or $_.name -like "*md5"} | 
     Sort-Object LastWriteTime -Descending | 
     Select-Object -First 20 `
      -Property @{L='Drv';E={($_.Name.substring(0,1))}}, `
                Name, `
                LastWriteTime, `
                @{L='Size';E={if ($_.Length -ge 1048576){'{0,14:N0} Mb   ' -f ($_.Length/1mb)}else{'{0,14:N0} bytes' -f ($_.Length)} }} |
     Sort-Object @{E='Drv'}, @{E={($_.Name.substring(12,$_.Name.Indexof(".")-12))};Descending=$true}, @{E='LastWriteTime';Descending=$true} | `
     ft -AutoSize -GroupBy Drv
    
  • #25461
    Profile photo of Alan B
    Alan B
    Participant

    ...and here's the 'final' version. Note that I found the line continuation characters were needed if the last character is not the pipe.

    Get-ChildItem | 
     Where-Object {$_.name -like "*spi" -or $_.name -like "*md5"} | 
     Sort-Object LastWriteTime -Descending | 
     Select-Object -First 20 `
      -Property @{L='Drv';E={($_.Name.substring(0,1))}}, `
                Name, `
                LastWriteTime, `
                @{L='Size';E={if ($_.Length -ge 1gb) {'{0,9:N2} Gb   ' -f ($_.Length/1gb)} `
                  elseif ($_.Length -ge 1mb) {'{0,9:N2} Mb   ' -f ($_.Length/1mb)} `
                  elseif ($_.Length -ge 1kb) {'{0,9:N2} Kb   ' -f ($_.Length/1kb)} `
                  else{'{0,9:N0} bytes' -f ($_.Length)} }} |
     Sort-Object Drv, @{E={($_.Name.substring(12,$_.Name.Indexof(".")-12))};Descending=$true}, `
               @{E='LastWriteTime';Descending=$true} | 
     ft -AutoSize -GroupBy Drv
    

    Thanks again for your help

  • #25492
    Profile photo of tommymaynard
    tommymaynard
    Member

    I'm not sure if this will be helpful or not, but this thread inspired me to write a post. If you check it out (link below), you'll see that I used a switch statement inside the Expression section of a calculated property. This allowed me to check each file's size (length), determine if it should be labeled with B, KB, MB, or GB, and then write that out with the modified value (divide by 1 MB, etc. depending). Thanks for the inspiration. I'll just leave this right here: [url]http://tommymaynard.com/script-sharing-return-file-sizes-in-bytes-kb-mb-and-gbs-at-the-same-time-2015/[/url].

  • #25525
    Profile photo of Rob Simmers
    Rob Simmers
    Participant

    Great post!! Thanks for posting the link.

You must be logged in to reply to this topic.