Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I return a custom object in Powershell that's formatted as a table?

Tags:

powershell

I'm pretty new to powershell, so I won't be surprised at all if I'm going about this all wrong. I'm trying to create a function that, when executed, prints results formatted as a table. Maybe it would even be possible to pipe those results to another function for further analysis.

Here's what I have so far. This is a simple function that iterates through a list of paths and collects the name of the directory and the number of items in that directory, putting the data in a hashtable, and returning an array of hashtables:

function Check-Paths(){
  $paths = 
    "C:\code\DirA",
    "C:\code\DirB"
  $dirs = @()
  foreach ($path in $paths){
      if (Test-Path $path){
        $len = (ls -path $path).length
      }
      else{
        $len = 0
      }
      $dirName = ($path -split "\\")[-1]
      $dirInfo = @{DirName = $dirName; NumItems = $len}
      $dirs += $dirInfo
  }
  return $dirs

}

That seems straightforward enough. However, when I go run the command, this is what I get:

PS > Check-Paths

Name                           Value
----                           -----
DirName                        DirA
NumItems                       0
DirName                        DirB
NumItems                       0

What I want is this:

DirName                       NumItems
-------                       --------
DirA                          0
DirB                          0

I could just hack my function to use a write statement, but I think there must be a much better way to do this. Is there a way to get the data formatted as a table, even better if that can be such that it can be piped to another method?

like image 789
Ben McCormack Avatar asked Dec 22 '22 01:12

Ben McCormack


2 Answers

How 'bout using

return new-object psobject -Property $dirs

That would return an object whose properties match the items in the hashtable. Then you can use the built-in powershell formatting cmdlets to make it look like you want. since you only have 2 properties, it will be formatted as a table by default.

EDIT: Here's how the whole thing would look (After the various suggestions):

function Check-Paths(){
  $paths = 
    "C:\code\DirA",
    "C:\code\DirB"
  $dirs = @()
  foreach ($path in $paths){
      if (Test-Path $path){
        $len = (ls -path $path).length
      }
      else{
        $len = 0
      }
      $dirName = ($path -split "\\")[-1]
      new-object psobject -property  @{DirName = $dirName; NumItems = $len}
  }
}
like image 161
Mike Shepard Avatar answered Dec 23 '22 15:12

Mike Shepard


Here's a one liner that will give you the number of children for each folder.

"C:\code\DirA", "C:\code\DirB" | ? {Test-Path $_} | Get-Item | select -property Name, @{ Name="NumOfItems" ; Expression = {$_.GetFileSystemInfos().Count} } 

It passes an array of strings to Where-Object to select the ones that exist. The path strings that exist are passed to Get-Item to get the FileSystemObjects which get passed to Select-Object to create PSCustomObject objects. The PSCustomObjects have two properties, the name of the directory and the number of children.

If you want the outputted table columns closer together you can pipe the above to: Format-Table -AutoSize

Example usage and output:

dir | ? {$_.PsIsContainer} | select -property Name, @{ Name="NumOfItems" ; Expression = {$_.GetFileSystemInfos().Count} } | Format-Table -AutoSize

Name         NumOfItems
----         ----------
Desktop              12
Favorites             3
My Documents          3
Start Menu            2
like image 23
Andy Arismendi Avatar answered Dec 23 '22 15:12

Andy Arismendi