I have two files being compared, one a CSV and one a txt file. The CSV file has the information for around 5,000 servers and the txt file has only server names for around 3,000. The columns within the CSV are Name, OS, and Type. This is what I did to compare the objects:
$compareObject = Compare-Object -ReferenceObject $txtFile -DifferenceObject $csvFile.Name -IncludeEqual
After this, I was then given three options. Ones that are on both lists ==
, ones that are only on the txt file =>
, and ones that are only on the csv file =<
.
What I'm trying to do is take the .SideIndicator
for values that equal ==
, and put that as a column within the $csvFile
so I can eventually do If ($csvFile.SideIndicator -eq "==")...
So basically I'm trying to figure out how to write:
If (($csvFile.Name -like $compareObject.InputObject) -and ($compareObject.InputObject -eq "==") {
(add .SideIndicator to CSV file)
}
I've tried placing a variable $count++
where I currently have add .SideIndicator...
within my script to see how many results return, and it always returns 0.
Can someone help me out with this or give me some ideas?
You want to pipe the results of Compare-Object
to endable the filtering of SideIndicator
like so:
$fields = "name", "street", "zip", "city"
Compare-Object -ReferenceObject $txtFile -DifferenceObject $csvFile.Name -IncludeEqual -Property $fields -PassThru | Where-Object {
$_.SideIndicator -eq "=="
} | Select-Object $fields | Export-Csv ".\output.csv" -NoTypeInformation
Where $fields
contain your CSV-Headers
This may be way too complicated, but here you go:
Suppose this is your CSV file:
"Name","OS","Type"
"htew804","Windows","WindowsAutherServer"
"wddg9028","Windows","WindowsAutherServer"
"other321","Windows","WindowsBackupServer"
and this is the content of your text file:
wddg9028
test1234
htew804
Then this code:
$csvFile = 'D:\blah.csv'
$txtFile = 'D:\names.txt'
# import the .csv file
$csv = Import-Csv -Path $csvFile
# read the .txt file which contains only server names, each on a separate line
$txt = Get-Content -Path $txtFile
$items = Compare-Object -ReferenceObject $txt -DifferenceObject $csv.Name -IncludeEqual -PassThru
$result = foreach ($item in $items) {
$name = $item.ToString()
switch ($item.SideIndicator) {
'<=' {
# the servername is only present in the text file
[PSCustomObject]@{
Name = $name
OS = ''
Type = ''
SideIndicator = $item.SideIndicator
Comment = "Name only found in $txtFile"
}
break
}
default {
# '==' AND '=>': the servername is only present in the csv file or in both files
$server = @($csv | Where-Object { $_.Name -eq $name })[0]
[PSCustomObject]@{
Name = $server.Name
OS = $server.OS
Type = $server.Type
SideIndicator = $item.SideIndicator
Comment = if ($item.SideIndicator -eq '==') { "Name found in both files" } else { "Name only found in $csvFile" }
}
}
}
}
$result | Format-Table -AutoSize
produces this result:
Name OS Type SideIndicator Comment
---- -- ---- ------------- -------
wddg9028 Windows WindowsAutherServer == Name found in both files
htew804 Windows WindowsAutherServer == Name found in both files
other321 Windows WindowsBackupServer => Name only found in D:\blah.csv
test1234 <= Name only found in D:\names.txt
If you want this info to be written to a new CSV file, change the Format-Table -AutoSize
into Export-Csv -Path 'D:\blah_updated.csv' -NoTypeInformation
- Taking Theo's sample files, but importing both files (the text file with
-Header Name
)
- and Razorfen's
-PassThru
approach,
- plus reversing the order to have the csv file as
-Reference
It's as easy as this:
$csvFile = Import-Csv .\sample.csv
$txtFile = Import-csv .\sample.txt -Header Name
Compare-Object -Ref $csvFile -Dif $txtFile -Property Name -IncludeEqual -PassThru
to get this desired output:
Name OS Type SideIndicator
---- -- ---- -------------
wddg9028 Windows WindowsAutherServer ==
htew804 Windows WindowsAutherServer ==
test1234 =>
other321 Windows WindowsBackupServer <=
So both get a +1 from me.