I've been working with PowerShell since the days of Monad and have written a lot of PowerShell scripts. Out of idle curiosity, and the need for a Friday Fun topic, I decided to see how many lines of PowerShell I have written. Or at least that are in my Scripts folder. Turns out I have 2003 ps1 files for a total of 143,375 lines of PowerShell. There's a bit of a fudge factor here has I often break single and long PowerShell expressions into multiple lines. So the number is an approximation. Here's how I figured this out.
ManageEngine ADManager Plus - Download Free Trial
Exclusive offer on ADManager Plus for US and UK regions. Claim now!
The Measure-Object cmdlet can also be used to measure text files. You can get values like total number of words, characters and lines. All you need to do is pipe content to the cmdlet.
PS C:\> get-content C:\scripts\Measure-ScriptLines.ps1 | measure-object -Line -Word -Character Lines Words Characters Property ----- ----- ---------- -------- 14 41 429
So to measure, let's say all of the script files I've created this year I can run a command like this:
PS C:\> dir c:\scripts\*.ps1 | where { $_.CreationTime -ge [datetime]"1/1/2014"} | get-content | measure -Line -IgnoreWhiteSpace Lines Words Characters Property ----- ----- ---------- -------- 2860
I included the parameter to skip blank lines. But I wanted a bit more information such as the total number of files and perhaps an average so I came up with this code.
dir c:\scripts\*.ps1 -recurse -ov a | get-content | measure -Line -IgnoreWhiteSpace | Select Lines, @{Name="TotalFiles";Expression={$a.count}}, @{Name="Avg";Expression={$_.lines/$a.count}}
When you use Measure-Object with the text parameters, you don't get a count property like you normally would. So I'm using one of the common parameters, OutVariable, which has an alias of OV, with Get-Childitem (the dir command). When using Out-Variable, the results are written to the pipeline and to the variable. This means I can use this variable later in my expression to create custom properties for the TotalFiles and Average.
Lines TotalFiles Avg ----- ---------- --- 143375 2003 71.5801298052921
Let's say I want the same results for all files created this year. I'll need to move my capture variable later in the expression:
dir c:\scripts\*.ps1 | where { $_.CreationTime -ge [datetime]"1/1/2014"} -ov a | get-content | measure -Line -IgnoreWhiteSpace | Select Lines, @{Name="TotalFiles";Expression={$a.count}}, @{Name="Avg";Expression={$_.lines/$a.count}}
I need to make sure my count and averages are based on the filtered results.
Lines TotalFiles Avg ----- ---------- --- 2860 24 119.166666666667
Or I can include unfiltered results as well.
PS C:\> dir c:\scripts\*.ps1 -Recurse -ov All | where { $_.CreationTime -ge [datetime]"1/1/2014"} -ov Filtered | get-content | measure -Line -IgnoreWhiteSpace | Select Lines, @{Name="TotalAllFiles";Expression={$All.count}}, @{Name="TotalFiltered";Expression={$Filtered.count}}, @{Name="PctTotal";Expression={($filtered.count/$All.count)*100}}, @{Name="Avg";Expression={$_.lines/$Filtered.count}} Lines : 2860 TotalAllFiles : 2003 TotalFiltered : 24 PctTotal : 1.19820269595607 Avg : 119.166666666667
I've added OutVariable to the first part of my expression. I also went ahead and used more meaningful variable names. Since I had the data, I decided to add a bit more data. Finally, even though I've primarily been using the count value for the variables, they hold full objects which leads to some intriguing possibilities:
PS C:\> dir c:\scripts\*.ps1 -Recurse -ov All | where { $_.CreationTime -ge [datetime]"1/1/2014"} -ov Filtered | get-content | measure -Line -IgnoreWhiteSpace | Select Lines, @{Name="TotalAllFiles";Expression={$All.count}}, @{Name="TotalAllKB";Expression={ ($all | Measure-Object -Property length -sum).sum/1KB }}, @{Name="TotalFiltered";Expression={$Filtered.count}}, @{Name="TotalFilteredKB";Expression={ ($Filtered | Measure-Object -Property length -sum).sum/1KB }}, @{Name="PctTotal";Expression={($filtered.count/$All.count)*100}}, @{Name="AvgLines";Expression={$_.lines/$Filtered.count}} Lines : 2860 TotalAllFiles : 2003 TotalAllKB : 6865.7890625 TotalFiltered : 24 TotalFilteredKB : 496.4453125 PctTotal : 1.19820269595607 AvgLines : 119.166666666667
So today's fun really covered two topics, using Measure-Object with text files and the OutVariable common parameter. Enjoy!
I’ve been using PowerShell for about 2 years now, and I didn’t know you could use Measure-Object like this. Thanks for writing this up – you’ve taught me something new today.
Thanks. That’s why I write these Friday Fun posts.