powershell group object and create csv with new header header - powershell

In Windows Powershell, how can I change the csv output format of executing this command:
$logs = 'System'
$today = (Get-Date).Date
$logs | foreach{
get-eventlog -log $_ -After ([datetime]::today) |
group eventid,EntryType -noel |
sort count -desc |
export-csv "eventLog_$_.csv" -notype
}
My output must be :
"Values","Count","Group","ID","Severity"
"System.Collections.ArrayList","1085","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","1501", "Information"
"System.Collections.ArrayList","15","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","37", "Information"
"System.Collections.ArrayList","13","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","1500", "Information"
"System.Collections.ArrayList","8","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","20001", "Information"
But when running the command above, I got this output instead:
"Values","Count","Group","Name"
"System.Collections.ArrayList","1085","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","1501,Information"
"System.Collections.ArrayList","15","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","37,Information"
"System.Collections.ArrayList","13","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","1500,Information"
"System.Collections.ArrayList","8","System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]","20001,Information"
Is there a better way than replacing with csv file modification ?

I not sure why you would want a bunch of lines in your file like "System.Collections.ArrayList" and so forth. You output that you should expect from your command is
Count Name
----- ----
116 7036, Information
5 7040, Information
1 206, Information
1 14204, Information
1 7001, Information
1 201, Information
The extra information can be stripped out with a simple Select-Object. The for each loop is not required unless you acutually have something more in $logs. If the case then you should have -Append on your Export-Csv. You also dont use $today
$logs = 'System'
get-eventlog -log $logs -After ([datetime]::today) |
Group-Object EventID,EntryType -NoElement |
Sort-Object Count -Descending |
Select-Object count,name |
Export-Csv C:\temp\test.txt -NoTypeInformation
A bonus to help
The above answer might be sufficient but this adds a little to it. I mentioned that your loop seemed odd. If you are looking at other logs than System then i could see a point. I have an example below. Also the return for Name contains both and eventID and EventType and we could do something about that. I create a PSCustomObject that splits the Name into its two parts.
$logs = 'System','Application'
$logs | ForEach-Object{
get-eventlog -log $_ -After ([datetime]::today) |
Group-Object EventID,EntryType -NoElement |
Sort-Object Count -Descending |
Select-Object count,name | ForEach-Object{
[PSCustomObject]#{
'EventID' = ($_.Name -split ", ")[0]
'EventType' = ($_.Name -split ", ")[1]
'Count' = $_.Count
}
}
} | Export-Csv C:\temp\test.txt -NoTypeInformation
The CSV output looks a little better now. The following is from the truncated csv
"EventID","EventType","Count"
"7036","Information","118"
"7040","Information","5"
"102","Information","1"
"902","0","1"
"300","Information","1"
"10","Error","1"
"302","Information","1"
If you only have powershell 2.0 you wont have access to [PSCustomObject] in which cause you could do the following instead. Notice the array $csv that is built in the ForEach loop and is then piped into Export-Csv
$csv = #()
$logs = 'System','Application'
$logs | ForEach-Object{
get-eventlog -log $_ -After ([datetime]::today) |
Group-Object EventID,EntryType -NoElement |
Sort-Object Count -Descending |
Select-Object count,name | ForEach-Object{
$properties = #{
'EventID' = ($_.Name -split ", ")[0];
'EventType' = ($_.Name -split ", ")[1];
'Count' = $_.Count;
}
$psobject = new-object psobject -Property $properties
$csv += $psobject
}
}
$csv | Export-Csv C:\temp\test.txt -NoTypeInformation

Related

Powershell import multiple csv and group by name and total up wins

I am trying to import multiple csv files and output a total score, i don't want to create another csv for the output, below is how the csv is stored. below is csv 1
and this is csv 2
i want to group by Name and total the wins, please see code below that i have tried
get-item -Path "File Path" |
ForEach-Object {
import-csv $_|
Group-Object Name
Select-Object Name, #{ n='Wins'; e={ ($_.Group | Measure-Object Wins -Sum).Sum } }
}
i was hoping for an outcome like below
any help would be awesome
for some reason the current code is showing the below
Its looking better but still not grouping on Name
This will give you the output you are expecting, with the names and total wins for each player.
$csv1 = import-csv "File path of CSV 1"
$csv2 = import-csv "File path of CSV 2"
$allRecords = $csv1 + $csv2
$allRecords | Group-Object Name | Select-Object Name, #{ n='Wins'; e={ ($_.Group | Measure-Object Wins -Sum).Sum } }
the ouptut
Update
With multiple Csv Files
$allRecords = #()
$directory = "Path of the directory containing the CSV files"
$filePaths = Get-ChildItem -Path $directory -Filter "*.csv"
foreach ($filePath in $filePaths) {
$csv = import-csv $filePath
$allRecords += $csv
}
$allRecords | Group-Object Name | Select-Object Name, #{ n='Wins'; e={ ($_.Group | Measure-Object Wins -Sum).Sum } }
If you have a very high number of csv files, you'll find something like this much faster:
$CombinedRecords = Get-ChildItem -Filter *.csv -Path C:\temp | Select-Object -ExpandProperty FullName | Import-Csv
$CombinedRecords | Group-Object Name | Select-Object Name, #{ n='Wins'; e={ ($_.Group | Measure-Object Wins -Sum).Sum } }
It can even be a one-liner:
Get-ChildItem -Filter *.csv -Path C:\temp | Select-Object -ExpandProperty FullName | Import-Csv | Group-Object Name | Select-Object Name, #{ n='Wins'; e={ ($_.Group | Measure-Object Wins -Sum).Sum } }

How can I select server name in below script using PowerShell?

$s = Get-Content #("C:\servers.txt") | ForEach-Object {
(Get-Acl $_ ).Access |
Select-Object IdentityReference, FileSystemRights, AccessControlType,
IsInherited
} | Export-Csv "C:\t8.csv" -NoTypeInformation -Encoding UTF8
You mean how you can add the servername as an additional column to the output CSV? Simply add it with a calculated property in the Select-Object:
$server = $_
(Get-Acl $server).Access |
Select-Object #{n='Servername';e={$server}}, IdentityReference, ...
Note that your assignment $s = ... is pointless, because all output goes to the CSV, so nothing is ever assigned to $s.

Parse csv along comparing txt file lined and log lines not found

As a continuation of a script I'm running, working on the following.
I have a CSV file that has formatted information, example as follows:
File named Import.csv:
Name,email,x,y,z
\I\RS\T\Name1\c\x,email#jksjks,d,f
\I\RS\T\Name2\d\f,email#jsshjs,d,f
...
This file is large.
I also have another file called Note.txt.
Name1
Name2
Name3
...
With help from #mathias-r-jessen
$Dir = PathToFile
$import = Import-Csv $Dir\import.csv
$NoteFile = "$Dir\Note.txt"
$Note = GC $NoteFile
$Import |Where-Object {$Note -contains $_.Name.Split('\')[4]} |Export-Csv "$Dir\Result.csv" -NoTypeInformation -Append
This code quickly and effortlessly parses the big csv and extracts every line that contains any of the lines in the $note file.
My next question is how do i log any lines in the $note file that were not found in the csv file.
I tried the following:
$result = $Import |Where-Object {$Note -contains $_.Name.Split('\')[4]} |Export-Csv "$Dir\Result.csv" -NoTypeInformation -Append
$Note | Where-Object {$result.Name.Split('\')[4] -notcontains $Note} | out-file $dir\not-found.log -append
This seems to return every line in $note.
#mathias-r-jessen any help you can provide would be appreciated.
You could use a Switch to do that.
Switch($Import){
{$Note -contains $_.Name.Split('\')[4]} {$_ | Export-Csv "$Dir\Result.csv" -NoTypeInformation -Append; continue}
default {$_ | Export-csv "$Dir\Not-Found.csv" -NoType -Append}
}
The continue in the first option makes it so that if the first case is a match it performs the relevant action, and then continues to the next record. If the first case doesn't match it moves on to the default action, which outputs it to a different file.
I solved it by using the following:
$result = $Import |Where-Object {$Note -contains $_.Name.Split('\')[4]}
$result | Export-Csv "$Dir\Result.csv" -NoTypeInformation -Append
$matches = $note | where-object { $result.Name -match $_}
compare-object $note $matches |where-object {$_.SideIndicator -like "<=" | select -ExpandProperty InputObject | Out-file "$Dir\Not_found.txt" -Append

Comparing two files: Single column in FirstFile - Multiple columns in SecondFile

I've figured out how to compare single columns in two files, but I cant figure out how to compare two files, with one column in the first and multiple columns in the second file. Both containing emails.
First file.csv (contains single column with emails)
john#email.com
jack#email.com
jill#email.com
Second file.csv (contains multiple column with emails)
john#email.nl,john#email.eu,john#email.com
jill#email.se,jill#email.com,jill#email.us
By comparing I would like to output, the difference. This would result in.
Output.csv
jack#email.com
Anyone able to help me? :)
Single columns comparison and output difference
#Line extracts emails from list
$SubscribedMails = import-csv .\subscribed.csv | Select-Object -Property email
#Line extracts emails from list
$ValidEmails = import-csv .\users-emails.csv | Select-Object -Property email
$compare = Compare-Object $SubscribedMails $ValidEmails -property email -IncludeEqual | where-object {$_.SideIndicator -eq "<="} | Export-csv .\nonvalid-emails.csv –NoTypeInformation
(Get-Content .\nonvalid-emails.csv) | ForEach-Object { $_ -replace ',"<="' } > .\nonvalid-emails.csv
Since the first file already contains email addresses per column, you can import it right away.
Take the second file and split the strings containing several addresses.
A new array with seperate addresses will be generated.
Judging from your output, you only seek addresses that are within the first csv but not in the second.
Your code could look like this:
$firstFile = Get-Content 'FirstFile.csv'
$secondFile = (Get-Content 'SecondFile.csv').Split(',')
foreach ($item in $firstFile) {
if ($item -notin $secondFile) {
$item | Export-Csv output.csv -Append -NoTypeInformation
}
}
If you want to maintain your code, can you consider a script like:
#Line extracts emails from list
$SubscribedMails = import-csv .\subscribed.csv | Select-Object -Property email
Rename-Item .\users-emails.csv users-emails.csv.bk
Get-Content .\users-emails.csv.bk).replace(',', "`r`n") | Set-Content .\users-emails.csv
#Line extracts emails from list
$ValidEmails = import-csv .\users-emails.csv | Select-Object -Property email
$compare = Compare-Object $SubscribedMails $ValidEmails -property email -IncludeEqual | where-object {$_.SideIndicator -eq "<="} | Export-csv .\nonvalid-emails.csv –NoTypeInformation
(Get-Content .\nonvalid-emails.csv) | ForEach-Object { $_ -replace ',"<="' } > .\nonvalid-emails.csv
Remove-Item .\users-emails.csv
Rename-Item .\users-emails.csv.bk users-emails.csv
or, more simplest
#Line extracts emails from list
$SubscribedMails = import-csv .\subscribed.csv | Select-Object -Property email
Get-Content .\users-emails.csv).replace(',', "`r`n") | Set-Content .\users-emails.csv.bk
#Line extracts emails from list
$ValidEmails = import-csv .\users-emails.csv.bk | Select-Object -Property email
$compare = Compare-Object $SubscribedMails $ValidEmails -property email -IncludeEqual | where-object {$_.SideIndicator -eq "<="} | Export-csv .\nonvalid-emails.csv –NoTypeInformation
(Get-Content .\nonvalid-emails.csv) | ForEach-Object { $_ -replace ',"<="' } > .\nonvalid-emails.csv
Remove-Item .\users-emails.csv.bk
None of the suggestions so far works :(
Still hoping :)
Will delete comment when happy :p
Can you try this?
$One = (Get-Content .\FirstFile.csv).Split(',')
$Two = (Get-Content .\SecondFile.csv).Split(',')
$CsvPath = '.\Output.csv'
$Diff = #()
(Compare-Object ($One | Sort-Object) ($two | Sort-Object)| `
Where-Object {$_.SideIndicator -eq '<='}).inputobject | `
ForEach-Object {$Diff += New-Object PSObject -Property #{email=$_}}
$Diff | Export-Csv -Path $CsvPath -NoTypeInformation
Output.csv will contain entries that exist in FirstFile but not SecondFIle.

Export-CSV exports length but not name

I have this code that I am running from powershell. When I run it without the export-csv i get all the folder names on the screen.
dir | select -expand fullname | % { ($_ -split '\')[7]
But if I add | export-csv c:\test.txt then I see following in the file not the folder name I expected just like I see it on the screen.
#TYPE System.String
"Length"
"13"
"18"
"20"
"22"
"29"
"21"
"24"
"11"
"17"
"20"
"20"
Export-Csv exports a table of object properties and their values. Since your script is producing string objects, and the only property they have is length, that's what you got.
If you just want to save the list, use Out-File or Set-Content instead of Export-Csv.
The previous answer does work, but what if someone was looking to output it into a CSV file.
This does NOT work:
$str_list = #('Mark','Henry','John')
$str_list | Export-Csv .\ExportStrList.csv -NoType
Because Export-Csv takes Objects and outputs properties. The only properties for a String[ ] is Length, so the CSV file only contains Lengths.
To fix this we need to change the String[ ] into an Object[ ]. The simplest way is with Select-Object.
Put each String into the Name property of a new Object[ ], like this:
$str_list = #('Mark','Henry','John')
$obj_list = $str_list | Select-Object #{Name='Name';Expression={$_}}
$obj_list | Export-Csv .\ExportStrList.csv -NoType
Just to re-iterate, Select-Object outputs a custom PSObject that can easily be manipulated. This is very powerful information, use it wisely.
This worked for me:
$data = #()
$row = New-Object PSObject
$row | Add-Member -MemberType NoteProperty -Name "name1" -Value "Test"
$row | Add-Member -MemberType NoteProperty -Name "name2" -Value 2
$data += $row
$data | Export-Csv "Text.csv" -NoTypeInformation
This is another way to handle this issue:
Out-File outputs by default
Define the master array list
$MASTER_ARRAY_LIST = [System.Collections.ArrayList]#()
Define the output filename
$OutputFilename="C:\TEMP\MyOutputFile.csv"
ForEach ( $Something in $List_of_Somethings) {
$CURRENT_RECORD_DETAILS = New-Object PSObject -Property #{'name'=$($Something.Name);'fullname'=$($Something.FullName);'id'=$($Something.ID)}
$MASTER_ARRAY_LIST.Add( $CURRENT_RECORD_DETAILS ) > $null
}
$MASTER_ARRAY_LIST.ToArray() | Select-Object -Property name,fullname,id | Export-Csv -Path $OutputFilename -NoTypeInformation
$test = #("test1","test2","test3")
$test | export-csv "firstTry.csv"
#We see that this fails. So here is how to to do it with the desired results
foreach ($item in $test) {
[ pscustomobject]#{ ResultColumn = $item } | Export-Csv -Path ./secondTry.csv -NoTypeInformation -Append
}
$output |Select-Object * | Export-Csv 'h:\filename.csv' -NoTypeInformation