Reputation: 21
Need help removing headers from a CSV file. The tool the files are being imported into has very stringent requirements. The top row has to be Title then row 2 date: 8/19/2019. Row three should contain data with no headers.
Tried to import it back and drop the top row using [1..-1] notation as well as tried to bring the data in with a Select-object -skip 1
. Still can't make it work.
Also tried writing the object array out to TXT but it only comes out as fields instead of being tab based like in CSV. Example:
Date: INfo: Field1:
get-content "c:\users\user123\documents\adh\_$(get-date (get-date).addDays($i) -f yyyy-MM-dd).csv" | Select-Object -Skip 1 | Set-Content "c:\users\user123\documents\adh\_$(get-date (get-date).addDays($i) -f yyyy-MM-dd).txt"
The file still contains the headers even after I tried to remove them.
Upvotes: 1
Views: 7685
Reputation: 437258
It sounds like your starting point is an in-memory object array, to be converted to CSV without headers.
To get a CSV representation without headers you needn't create an intermediate file with Export-Csv
- simply pipe to ConvertTo-Csv
, which produces an array of strings, whose first element - the header row - you can skip with Select-Object -Skip 1
.
Your entire file can therefore be written via a single expandable here-string:
# Format the date string.
$i = 2 # sample value
$dateString = '{0:yyyy-MM-dd}' -f (Get-Date).AddDays($i)
# The input object array
# $objArray = ...
# Use an expandable here-string to write the output file.
@"
Title
$dateString
$($objArray | ConvertTo-Csv | Select-Object -Skip 1 | Out-String)
"@ | Set-Content -NoNewline "c:\users\user123\documents\adh\_$dateString.txt"
As for what you tried:
tried to import it back and drop the top row using [1..-1] notation
[1..-1]
does not skip the first element of an array in PowerShell, because 1..-1
is a range expression that expands to the following list of indices: 1, 0, -1
; that is, you're extracting exactly 3 elements: the 2nd (1
), the first (0
), and the last one (-1
).
Also tried writing the object array out to TXT but it only comes out as fields instead of being tab based like in CSV. Example:
That sounds like you sent your in-memory object array to a *.txt
file using something other than Export-Csv
, which won't give you CSV output; it sounds like you used >
or Out-File
, where objects are formatted the same way they'd print to the console, which is a for-display format, not one suitable for programmatic processing.
get-content ....csv | Select-Object -Skip 1 | Set-Content ....txt
That command should work, assuming that the input *.csv
file was created with
Export-Csv -NoTypeInformation
.
If you didn't use -NoTypeInformation
, use -Skip 2
, i.e., skip an additional line, so as to skip the type-annotation line that Export-Csv
- unfortunately - outputs as the 1st line by default.
Note: This counter-intuitive default behavior of Export-Csv
in Windows PowerShell has been fixed in PowerShell Core.
Upvotes: 1
Reputation:
Given a generated sample file:
> Get-Content .\_2019-08-19.csv
"COLA","ColB"
"Test1","Foo"
"Test2","Baz"
"Test3","Bar"
"Test4","Baz"
"Test5","Baz"
This script:
## Q:\Test\2019\08\20\SO_SO_57581085.ps1
##
$i = 1
$BaseDir = 'C:\Users\user123\Documents\adh'
# $BaseDir = (gi .).FullName
$BaseName= '_{0:yyyy-MM-dd}' -f (Get-Date).AddDays(-$i)
"Your Title`ndate: {0:M\/d\/yyyy}" -f (Get-Date).AddDays(-$i) |
Set-Content (Join-Path $BaseDir ($BaseName+'.txt')) # -Encoding if req.
Get-Content (Join-Path $BaseDir ($BaseName+'.csv')) |
Select-Object -Skip 1 |
Add-Content (Join-Path $BaseDir ($BaseName+'.txt')) # -Encoding if req.
Yields this result file:
> Get-Content .\_2019-08-19.txt
Your Title
date: 8/19/2019
"Test1","Foo"
"Test2","Baz"
"Test3","Bar"
"Test4","Baz"
"Test5","Baz"
Upvotes: 1
Reputation: 16236
The file can be constructed after you get the .csv file that contains a field header record. The csmem.csv
file has been produced, but has a header record. This will write the title and date on the first two (2) records, then append the .csv file without the header record.
"The Title" | Out-File -FilePath "C:\src\t\sf.csv" -Encoding ascii
(Get-Date).ToString('yyyy-MM-dd') | Out-File -FilePath "C:\src\t\sf.csv" -Encoding ascii -Append
Get-Content -Path 'C:\src\t\csmem.csv' |
Select-Object -Skip 1 |
Out-File -FilePath "C:\src\t\sf.csv" -Encoding ascii -Append
Upvotes: 1
Reputation: 403
I was able to reproduce your issue by generating a test CSV like so:
Get-Process | Select ProcessName, ID, SI | Export-CSV C:\temp\test.csv -NoTypeInformation
What you've stumbled upon is an interesting aspect of the pipeline. I don't know the specifics of WHY it's doing what it's doing, but you have two ways of working around it automatically putting the headers back in the CSV:
Get-Content C:\temp\test.csv | Select -Skip 1 | Out-File -FilePath "C:\temp\new.csv" -NoClobber
The caveat here is that it won't let you overwrite the file you've opened with Get-Content so you'll have to send it to a separate fileGet-Content C:\temp\test.csv | Select -Skip 1
into a variable and then sending that variable to a regular Out-File call. This would let you overwrite the file.Upvotes: 0
Reputation: 301
Copy the file on a test environment, try to add -NoTypeInformation this might solve your problem.
-NoTypeInformation will remove the metadata, so be careful in the testing.
Upvotes: 0