Append filename to CSV in new column - powershell

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.

Related

Powershell - Extract first line from CSV files and export the results

Thanks in advance for the help.
I have a folder with multiple CSV files. I’d like to be able to extract the first line of each of the files and store the results in a separate CSV file. The newly created CSV file will have the first column as the file name and the second column to be the first line of the file.
The output should look something like this (as an exported CSV File):
FileName,FirstLine
FileName1,Col1,Col2,Col3
FileName2,Col1,Col2,Col3
Notes:
There are other files that should be ignored. I’d like the code to loop through all CSV files which match the name pattern. I’m able to locate the files using the below code:
$targetDir ="C:\CSV_Testing\"
Get-ChildItem -Path $targetDir -Recurse -Filter "em*"
I’m also able to read the first line of one file with the below code:
Get-Content C: \CSV_Testing\testing.csv | Select -First 1
I guess I just need someone to help with looping through the files and exporting the results. Is anyone able to assist?
Thanks
You basically need a loop, to enumerate each file, for this you can use ForEach-Object, then to construct the output you need to instantiate new objects, for that [pscustomobject] is the easiest choice, then Export-Csv will convert those objects into CSV.
$targetDir = "C:\CSV_Testing"
Get-ChildItem -Path $targetDir -Recurse -Filter "em*.csv" | ForEach-Object {
[pscustomobject]#{
FileName = $_.Name
FirstLine = $_ | Get-Content -TotalCount 1
}
} | Export-Csv path\to\theResult.csv -NoTypeInformation
I have assumed the files actually have the .Csv extension hence changed your filter to -Filter "em*.csv", if that's not the case you could use the filter as you currently have it.

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 Compare 2 CSV but highlight duplicates or create a new column

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

Count Rows in CSV files and export results to CSV

I am trying count the rows containing values in a bunch of CSV in a folder. I managed to get the code to count it but I can't seem to find a way to export the results to a CSV. All I got is a blank CSV.
What am I missing here?
$FOLDER_ROOT = "C:\Test\2019"
$OUTPUT_CSV = "C:\Test\2019\Count.csv"
Get-ChildItem $FOLDER_ROOT -re -in "*.csv" | ForEach-Object {
$filestats = Get-Content $_.Fullname | Measure-Object -Line
$linesInFile = $filestats.Lines - 1
Write-Host "$_,$linesInFile"
} | Export-Csv -Path $OUTPUT_CSV -NoType
There are several issues with your code:
Use Get-ChildItem -Filter '*.csv' instead of Get-ChildItem -Include '*.csv'. The former is faster than the latter.
Write-Host most likely causes the output to go directly to the host console. I've been told that this was changed in recent versions (so that host output goes to the new information stream), but for versions at least prior to v5 it's still a reality.
Export-Csv expects object input, since it outputs the properties of the objects as the fields of the CSV (taking the column titles from the property names of the first object). Feeding it strings ("$_,$linesInFile") will result in a CSV that contains only a column "Length", since that is the only property of the string objects.
Use a calculated property for creating a CSV with the filename and line count of the input files:
Get-ChildItem $FOLDER_ROOT -Recurse -Filter '*.csv' |
Select-Object Name, #{n='LineCount';e={(Get-Content $_.Fullname | Measure-Object -Line).Lines - 1}} |
Export-Csv $OUTPUT_CSV -NoType
Write-Host writes only to the host! Most probably you see the output into the PowerShell Console?
Use Write-Output, which could be piped to Export-CSV.

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.