Skipping empty CSV objects
Working with CSV files in PowerShell is a common practice. You import the file, loop on its records and you’re good to go. Sometimes however you may find yourself in a situation where you get a file that has blank lines in it, and those lines can break your script. Consider the following CSV content:
## sample.csv ## column1,column2,column3 Value1,Value2,Value3 Value1,Value2,Value3 <empty line> <empty line> <empty line> ## file ends here
On the surface, nothing looks suspicious when you import the file:
PS> Import-Csv sample.csv
column1 column2 column3
------- ------- -------
Value1 Value2 Value3
Value1 Value2 Value3
PS>
But if you pipe it to Format-List you can clearly see what’s going on. You get empty objects for each empty line in the file.
PS> Import-Csv sample.csv | Format-List
column1 : Value1
column2 : Value2
column3 : Value3
column1 : Value1
column2 : Value2
column3 : Value3
column1 :
column2 :
column3 :
column1 :
column2 :
column3 :
column1 :
column2 :
column3 :
To filter out empty objects you need to test that all properties are not equal to an empty string and throw them away.
You might be attempted to do that with:
Import-Csv sample.csv | Where-Object {$_.column1 -ne '' -and $_.column1 -ne '' -and $_.column1 -ne ''}
But what if each record has 20 properties, or even more? This is where the PSObject property comes to rescue. In a nutshell, PSObject allows us to work with any object in the same way without really knowing its structure. PowerShell wraps the base object in a PSObject and provide us a simplified and consistent view of the object, its methods, properties, and so on. One of the properties of PSObject is Properties, and it gives us a list of properties of the base object.
On a related note, PSObject and other members are not visible when you pipe an object to the Get-Member cmdlet. To reveal those members add the -Force switch to Get-Member.
For our purpose, we can process the properties list and filter out those who have a Value of null.
Import-Csv sample.csv |
Where-Object { ($_.PSObject.Properties | ForEach-Object {$_.Value}) -ne $null} |
Format-List
column1 : Value1
column2 : Value2
column3 : Value3
column1 : Value1
column2 : Value2
column3 : Value3
In PowerShell 3.0 and the new Member Enumeration feature we can get the same result in less characters:
Import-Csv sample.csv | Where-Object { $_.PSObject.Properties.Value -ne $null}
I logged an Import-Csv feature enhancement, and you can add your vote if you’d like to have a built-in option of ignoring empty lines.
Share on: