Powershell Compare 2 CSV but highlight duplicates or create a new column - powershell

I'm trying to compare 2 csv files and highlight the duplicates or add a separate column flag with text to let them know it is a duplicate. Right now I can generate a separate csv with only the changes but I would like to keep everything in the original csv and I just wanted to see if it could be done.
Here is my code to remove the duplicates into another csv:
$csv2 = (Import-Csv -Path \.csv).Primaryemail
$removedDuplicateRows = Import-Csv -Path \.csv | Where-Object {$_.Associate_Email -in $csv2}
$removedDuplicateRows | Export-Csv -Path \.csv -NoTypeInformation

Related

Export-CSV Filtering

$Headers = "Username"
Import-CSV -Path "$WorkingFolder\Test.csv" | Select $Headers | Export-CSV -Path "$WorkingFolder\Master.txt" -Force -NoTypeInformation
I am exporting a CSV File as a .txt file and only want to select the data from the Username column. It succesfully outputs as a .txt file and select all the items listed as Usernames. but contains "Information" and the header in the .txt file. I just want the raw data and want to remove the quotation marks and the header. I understand already that I can just skip the first row for exporting if need be but was going to see if there was another way round this.
I guess then what you want is
(Import-Csv -Path "$WorkingFolder\Test.csv").UserName |
Set-Content -Path "$WorkingFolder\Master.txt"
P.S. Personally, I would rather use Join-Path -Path $WorkingFolder -ChildPath 'test.csv' to make sure you get the path separator correct

Powershell Import-CSV: either reorder columns with no headers or export-CSV with no header

I have a CSV file with no headers in which I need to add a column between the first and second column. I ultimately want to export the file with no headers to the same file name (hence why I'm using Import-CSV vs Get-Content).
Here is the script which adds the new column to the existing file:
(Import-CSV U:\To_Delete\Layer_search\WB_layers-mod.csv) |
Select-Object *,#{Expression={'FALSE'}} |
Export-Csv U:\To_Delete\Layer_search\WB_layers-mod.csv -NoTypeInformation
This adds the a new column as a third column. In doing my googling, I could find no way to reorder the columns without having a header row, so I modified the script as follows:
(Import-CSV U:\To_Delete\Layer_search\WB_layers-mod.csv -header H1, H2)|
Select-Object *,#{Name='H3';Expression={'FALSE'}} |
Select-Object -Property H1, H3, H2 |
Export-Csv U:\To_Delete\Layer_search\WB_layers-mod.csv -NoTypeInformation
This puts the columns in the correct order, but now I want to export the CSV without the header row I added. However, the only suggestions I'm finding are using Get-Content, Convert-to-CSV, and using Skip 1. That won't work for me because I'm only running PS3 and that option is not available until PS5, and I want to save back to the original file name, which you can't do with Get-Content.
I'm probably making this a lot harder than it needs to be, but I would appreciate any suggestions.
Thanks!
Edited to add:
For clarification, here is an example of the CSV file I am importing:
abc,1/1/2012
def,1/2/2012
ghi,1/3/2012
I want to add a column between the first and second columns:
abc,FALSE,1/1/2012
def,FALSE,1/2/2012
ghi,TRUE,1/3/2012
Hopefully this makes more sense.
I'd read Headers H1,H3 and calculate H2 to have them in the proper order directly.
(Import-CSV .\sample.csv -header H1, H3)|
Select-Object H1,#{Name='H2';Expression={'FALSE'}},H3 |
ConvertTo-Csv -NoTypeInformation | Select-Object -Skip 1 | Set-Content New.csv
Sample output
"abc","FALSE","1/1/2012"
"def","FALSE","1/2/2012"
"ghi","FALSE","1/3/2012"

How can I alternate column headers in a tab delimited file?

I have a tab delimited txt file and i need to switch first and second column names (without switching columns data). In other words I need to rename A(Id) to B(ExternalId) and B(ExternalId) to A(Id). Other columns in the file (other data) should stay unchanged. I'm very new in PowerShell, please advice. As I understand I need to use import/export csv cmdlet.
I tryed this, but it's not working the right way...
Import-Csv 'C:\original_users.txt' |
Select-Object Id, #{Name="ExternalId";Expression={$_."Id"}}; Select-Object ExternalId, #{Name="Id";Expression={$_."ExternalId"}} |
Export-Csv 'C:\changed_users.txt'
The Import-CSV and Export-CSV cmdlets have their strengths but this might not be one of them. The latter cmdlet would introduce quoting that might not be in your original file and that might not be desired.
Either way why not just do some text manipulation on the first line! Lets read in the file and and output the first lined, edited, and the remainder of the file. This sample uses a new location but you could easily write it back to the same file.
# Get the full file into a variable
$fullFile = Get-Content "c:\temp\mockdata.csv"
# Parse the first line into a column array
$columns = $fullFile[0].Split("`t")
# Rebuild the header by switching the columns order as desired.
$newHeader = ($columns[1],$columns[0] + ($columns | Select-Object -Skip 2)) -join "`t"
# Write the header back to file then the rest of the data.
$outputPath = "C:\somepath.txt"
$newHeader | Set-Content $outputPath
$fullFile | Select-Object -Skip 1 | Add-Content $outputPath
This also preserves the presence of other columns and their data.

Append filename to CSV in new column

I have a lot of csv files stored in a directory.
In each csv file need to add the name as column this through powershell.
Example
File location: <SERVERNAME>\Export\FILENAME1.CSV
Contents:
1232;Description;a1
1232;Description;a2
The result must be:
1232;Description;a1;FILENAME1.CSV
1232;Description;a2;FILENAME1.CSV
Can someone help me with this?
The following will append a Filename column to each .CSV file in a directory:
Get-ChildItem *.csv | ForEach-Object {
$CSV = Import-CSV -Path $_.FullName -Delimiter ";"
$FileName = $_.Name
$CSV | Select-Object *,#{N='Filename';E={$FileName}} | Export-CSV $_.FullName -NTI -Delimiter ";"
}
Explanation:
Uses Get-ChildItem to get all files named *.csv
Iterates through each file with ForEach-Object and uses Import-CSV to load their contents as a PowerShell object
Records the name of the file in $FileName
Uses Select-Object to add a calculated property with the name Filename and the value of the $FileName variable
Uses Export-CSV to write back over the original file. The -NTI (NoTypeInformation) switch is used to ensure the PowerShell object header line is not included.
Mark Wragg's PowerShell code works, but I had to change the delimiter to , instead of ; so that it opens in Excel. I'm trying to figure out how to append the filename to the first column instead of the last because my files don't have the same number of fields so they don't align.

Using duplicate headers in Powershell .csv file

I have a .csv file and I want to import it into powershell then iterate through the file changing certain values. I then want the output to append to the original .csv file, so that the values have been updated.
My issue is that the .csv file has headers which aren't unique, and can't be changed as then it won't work in another program. Originally I defined my own headers in the powershell to get around this but then the output file has these new headers when it needs to have the old ones.
I have also tried ConvertFrom-Csv which means I can no longer access the columns I need to, so lots of runtime errors.
What would be ideal is to be able to use the defined column headers and then convert back to the original column headers. My current code is below:
$csvfile = Import-Csv C:\test.csv| Where-Object {$_.'3' -eq $classID} | ConvertFrom-Csv
foreach($record in $csvfile){
*do something*}
$csvfile | Export-Csv -path C:\test.csv -NoTypeInformation -Append
I've searched the web now for some hours and tried everything I've come across, to no avail.
Thanks in advance.
This is a somewhat hackish implementation but should work.
Remove all the headers as a single line and save it somewhere
Parse the new result-set (with the headers removed)
Add the line at the top when you are finished
A CSV is a comma delimited file, you don't have to treat it like structured data. Feel free to splice and dice as you want.
Since you know beforehand how many columns are in the input CSV file, you can import without the header and process internally. Example:
$columns = 78
Import-Csv "inputfile.csv" -Header (0..$($columns - 1)) | Select-Object -Skip 1 | ForEach-Object {
$row = $_
$outputObject = New-Object PSObject
0..$($columns- 1) | ForEach-Object {
$outputObject | Add-Member NoteProperty "Col$_" $row.$_
}
$outputObject
} | Export-Csv "outputfile.csv" -NoTypeInformation
This example generates new PSObjects and then outputs a new CSV file with generic column names (Col0, Col1, etc.).