views:

469

answers:

6
+4  Q: 

Powershell "join"

Call me stupid, but I'm losing my hair with this one.

I have two results from a Get-WmiObject:

$cpu = Get-WmiObject -Class Win32_Processor 
$mb = Get-WmiObject -Class Win32_BaseBoard

Now, I can filter and output a CSV file from each one:

$cpu | Select-Object Name, Description | ConvertTo-Csv -NoTypeInformation

and

$mb | Select-Object Manufacturer, Product | ConvertTo-Csv -NoTypeInformation

But... How the hell could I join these two outputs and make a single CSV output from both? Something like:

( 
  ($cpu | Select-Object Name, Description) + 
  ($mb | Select-Object Manufacturer, Product) 
) | ConvertTo-Csv -NoTypeInformation

(of course, this syntax is invalid. Just to show the point)

A: 

You can always add whatever properties you need to a custom powershell object that has what you need and then dump the cvs. Take a look at this page and see if it suites what you need.

rerun
There MUST be a better (simpler) way instead of Add-Member...
rookie
There is, in PowerShell 2, see the example by @dangph
Jaykul
+1  A: 

How about like this?

echo $cpu $mb | Select-Object Name, Description, Manufacturer, Product | ConvertTo-Csv -NoTypeInformation
S.Mark
Almost! This actually returns four columns, but in *TWO* lines. Each line containing two values and two nulls. Now, if we could make a kind of "union"...
rookie
There is `-join "a","b"`, I am trying to figure out how to use it.
S.Mark
+5  A: 

You need Powershell V2 for the following.

$cpu = Get-WmiObject -Class Win32_Processor 
$mb = Get-WmiObject -Class Win32_BaseBoard
$props = @{            
    Name          = $cpu.Name
    Description   = $cpu.Description
    Manufacturer  = $mb.Manufacturer
    Product       = $mb.Product
    }
New-Object PSObject -Property $props | ConvertTo-Csv -NoTypeInformation

In a happy coincidence, I learned about this technique when it appeared on the PowerShell Blog just an hour ago.

dangph
A: 

$cpu | Select-Object Name, Description | add-member noteproperty Manufacturer $mb.Manufacturer -PassThru | add-member noteproperty Product $mb.Product -PassThru

Shay Levy
A: 

Is this what you are looking for? Somewhat longer then I expected, because both $cpu and $mb have Name and Manufacturer properties. But the prime idea is the custom objects through hashing.

($cpu | Select-Object Name, Description),($mb | Select-Object Manufacturer, Product) | 
       Select-Object @{name='NameOrManu';expr={$_.Name + $_.Manufacturer}},  
                     @{name='DescrOrProd';expr={$_.Description + $_.Product}} | 
       ConvertTo-Csv -NoTypeInformation
Jacques Willemen
+1  A: 

There's a Join-Object function on PoshCode for doing this, but it's buried inside Join-Collection and not exported.

 function Join-Object {
    Param(
       [Parameter(Position=0)]
       $First
    ,
       [Parameter(Position=1,ValueFromPipeline=$true)]
       $Second
    )
    BEGIN {
       [string[]] $p1 = $First | gm -type Properties | select -expand Name
    }
    Process {
       $Output = $First | Select $p1
       foreach($p in $Second | gm -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name) {
          Add-Member -in $Output -type NoteProperty -name $p -value $Second."$p"
       }
       $Output
    }
 }

Once you've defined that, you can use it like this:

Join-Object (Get-WmiObject -Class Win32_Processor) (Get-WmiObject -Class Win32_BaseBoard) | 
Select Name, Description, Manufacturer, Product

Or keep your variables, and do it like:

$cpu = Get-WmiObject -Class Win32_Processor 
$mb = Get-WmiObject -Class Win32_BaseBoard

Join-Object $cpu $mb  | Select Name, Description, Manufacturer, Product
Jaykul