2

I am writing a powershell script to calculate summary stats for a csv file with 100,000+ rows.

In my foreach loop, one of my lines is:

$count = $Not_10000.count

Where "$Not_10000" is the result after filtering a csv, which was read using the import-csv command and filtered using

where {$_.ifhighspeed -eq 10000}.

I found that the value of "$count" is correct whenever "$Not_10000" has more than one line. However, when "$Not_10000" only has one line, the result is that $count is empty. I tried going into the powershell prompt and doing

$count = $Not_10000 | Measure-Object -lines

But it shows 0 lines even though it has one line. The output of

$Not_10000[0]

is

DATE                       ENTITYNAME     IFHIGHSPEED
----                       ----------     -----------
8/25/2014 12:00:00 AM      SF15-0326      1000

Why wouldn't this one line output be counted correctly? I manually changed the filters to make "$Not_10000" contain 15 lines, and this was counted correctly.

I seem to have trouble in general giving the full picture, so let me know if you need more info or clarification.

3
  • 1
    While i can replicate this i get 0 whenever i use -line on objects. -line is more for text. Measure-Object on its own and capture the Count property? $count = ($Not_10000 | Measure-Object).Count Commented Aug 27, 2014 at 15:53
  • Thank you! ($Not_10000 | Measure-Object).Count worked as I needed. Not sure why $Not_1000.count didn't work though. Commented Aug 27, 2014 at 16:00
  • Count is a property of Measure-Object not the Csv-object. See my answer and if it helps mark it as such. Commented Aug 27, 2014 at 16:05

2 Answers 2

6

Matt gives a good answer, but is only kind of the answer to your question.

The .Count property is a member of the Array object type that is being referenced when the number of results is more than one. When you only have one result then what is returned is not an array, it is a String, or an Object, or an Integer or something, but not an array unless you specifically make it one. In order for this to always come back with a number:

$count = $Not_10000.count

You need to cast it as an array, which is most simply done by enclosing it in @()

$count = @($Not_10000).count

This is most easily seen by using the .PSObject member of any object, when used on an array. Let's create an array, and look at the Type to verify that it's an array, and then look at the PSObject members (filtering for just properties, since it has a lot of members we don't care about) for that array object.

PS C:\Users> $test = @("Red","Blue","Green")

PS C:\Users> $test.GetType()

IsPublic IsSerial Name                                     BaseType                                 
-------- -------- ----                                     --------                                 
True     True     Object[]                                 System.Array                             

PS C:\Users> $test.PSObject.Members | Where{$_.MemberType -match "property"}|FT Name,MemberType,Value,ReferencedMemberName

Name                                    MemberType                    Value ReferencedMemberName    
----                                    ----------                    ----- --------------------    
Count                                AliasProperty                        3 Length                  
Length                                    Property                        3                         
LongLength                                Property                        3                         
Rank                                      Property                        1                         
SyncRoot                                  Property       {Red, Blue, Green}                         
IsReadOnly                                Property                    False                         
IsFixedSize                               Property                     True                         
IsSynchronized                            Property                    False                         
Item                         ParameterizedProperty ...int index) {get;set;} 

What we see here is that it is an AliasProperty for the member Length, which on an array gives the number of records, just like it's alias Count does.

Sign up to request clarification or add additional context in comments.

1 Comment

+1 Good work on supplementing my answer. It does look like i glazed over that fact.
3

Use the Count property of Measure-Object. Lines, Words, Characters are things you use to measure text not objects

$count = $Not_10000 | Measure-Object | Select-Object -ExpandProperty Count

or

$count = ($Not_10000 | Measure-Object).Count

More Explanation

I have a csv with a header and 7 entries.

Path                                    Data                                    Files
----                                    ----                                    -----
\\someserver\somepath1                  100                                     1
\\someserver\somepath2                  150                                     4
\\someserver\somepath1                  200                                     5
\\someserver\somepath3                  450                                     8
\\someserver\somepath4                  200                                     23
\\someserver\somepath1                  350                                     2
\\someserver\somepath2                  800                                     9

When i do the following (-lines is not a valid switch for Measure-Object )

Import-Csv E:\temp\stack.csv | Where-Object{$_.Data -gt 300} | Measure-Object -line

Since this is not text there are no lines to measure. I get this output regardless of how many entries in the file or filtered object. You would expect 3 but you actually get 0

Lines Words                         Characters                    Property
----- -----                         ----------                    --------
    0

If i read the file as text i would get a result for lines

Get-Content E:\temp\stack.csv | Measure-Object -line

 Lines
 -----
     8

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.