I'm trying to get the line count of a csv file. I ran this code to get it:
$csvPath = "some.csv"
$lineCount = "linecount.csv"
Import-Csv $csvPath | Select-Object -Skip 1 | Measure-Object | Export-CSV $lineCount -NoTypeInformation
This is the output I get in linecount.csv:
"Count","Average","Sum","Maximum","Minimum","Property"
"100",,,,,
This is my desired output:
"Count"
"100"
How can I achieve this?
To select a subset of the properties from an object / each object in a collection, pipe them to
Select-Objectand pass the property names of interest to the-Propertyparameter.Therefore, to get only the
Countproperty (using a simplified example):Note:
For each input object,
Select-Objectoutputs a[pscustomobject]instance that contains the specified properties.[1]In addition to selecting existing properties as-is, you may define calculated properties, which can be used to define properties with values derived from the input objects' property values, to rename properties, or to add entirely new properties.
If you pipe the above to
Export-Csv, you'll get the desired CSV output; to verify this in memory, pipe toConvertTo-Csvinstead.By contrast, if you merely want the value of the
Countproperty (rather than an object with aCountproperty), you can use-ExpandPropertyinstead of-Propertyor pipe to| ForEach-Object Countinstead; however the following is more concise and efficient:[2]As for you what you're counting:
If you want to determine the the number of data lines in your input CSV files - excluding the header line, use plain-text processing via
Get-Contentinstead ofImport-CsvCSV rows can span more than line, so this method will only report the correct count if all rows, including the header row, occupy exactly one line each (while that is typical, it isn't guaranteed).
As Santiago points out, this method can perform poorly with large input files, in which case you're better off using the approach shown in this answer.
If you want the number of data rows in your input CSV file,
Import-Csvis all you need: no need forSelect-Object -Skip 1, because whatImport-Objectreturns are objects representing just the data rows - the header information is "baked into" each such object, in the form of the object's property names:Note:
Get-Contentmethod.[1] In an effort to reflect the type of the objects that the properties were taken from, the output objects are assigned an additional type name, via PowerShell's ETS (Extended Type System), formed by prepending
Selected.to the full type name of the input objects. In this example:Selected.Microsoft.PowerShell.Commands.GenericMeasureInfo. This ETS type name surfaces when you pass such instances toGet-Member, for instance, and also as the first entry of the instrinsic.pstypenamesproperty value and in the type-identifying comment added to CSV output byExport-Csv/ConvertTo-Csvif-NoTypeInformationis not used in Windows PowerShell / if-IncludeTypeInformationis used in PowerShell (Core) 7+.[2] This even works with multiple input objects, courtesy of PowerShell's member-access enumeration feature. However, this requires collecting all input objects in memory, up front. While this generally won't be a problem, it could be with large input collections where processing the property values one by one must be performed; in that case, use the
Select-ObjectorForEach-Objecttechniques.