October 9th, 2011

Use a PowerShell Cmdlet to Count Files, Words, and Lines

Doctor Scripto
Scripter

Summary: Learn how to use a powerful Windows PowerShell cmdlet to count words and lines in files, or to count files.

 

Microsoft Scripting Guy Ed Wilson here. The weekend is halfway over in Charlotte, North Carolina. For my friends in Australia, the weekend is already over, and they are on their way to work. Of course they get to start their weekend earlier than I do. The ideal thing to do is to be in Australia to start the weekend, and then pop back to Charlotte to conclude the weekend. Yes, I have strange thoughts on the weekend. For example, I was on the treadmill earlier, and I was thinking about my favorite Windows PowerShell cmdlet. Anyway, I called the Scripting Wife while I was cooling down. She was downstairs and it is easier to call her than to go down there. Cell phones make great intercoms.

“What are you doing?” she asked as she answered her Windows 7 phone.

“I just finished running on the treadmill, and I am now cooling down. I was wondering what your favorite Windows PowerShell cmdlet is.”

“You have got to be kidding. Why would I have a favorite Windows PowerShell cmdlet?” she asked.

“Well, I was thinking about my favorite Windows PowerShell cmdlet while I was running, and I realized I did not know what yours was,” I said.

“Get-Real,” she said as she hung up.

At times, I think that the Scripting Wife seems to believe I am a nerd. I am not positive of this and am somewhat afraid to ask, but she seems to give off the “nerd alert” vibe when I enter a room or when I call her on her cell phone from upstairs and ask her about her favorite Windows PowerShell cmdlet.

Anyway, I will share my favorite cmdlet—it is the Measure-Object cmdlet. If I did not have the Measure-Object cmdlet, I would need to count the files in a folder manually. This is shown here:

$i=0

Get-ChildItem -Path c:\fso -Recurse -Force |

foreach-object { $i++ }

$i

 

Using the Measure-Object cmdlet, it is easy to count the files. I merely need to use the following steps.

  1. Use the Get-Childitem cmdlet to return a listing of fileinfo objects. Use the recurse switch to cause the cmdlet to work through subfolders. The force switch is used to return any hidden or system files. Pass the path to count to the path parameter.
  2. Pipe the fileinfo objects from step one to the Measure-Object cmdlet

An example of using this command to count the files in the c:\fso folder is shown here:

Get-ChildItem -Recurse -force | Measure-Object

The command and associated output are shown in the following figure. Note that I ran the command twice: the first time without the force switched parameter, and the second time using it.

Image of command and associated output

But the Measure-Object cmdlet does more than just count the number of files in a folder. It can also tell me information about a text file. A sample file is shown in the following figure.

Image of sample file

If I want to know how many lines are contained in the file, I use the Measure-Object cmdlet with the line switch. This command is shown here:

Get-Content C:\fso\a.txt | Measure-Object –Line

If I need to know the number of characters, I use the character switch:

Get-Content C:\fso\a.txt | Measure-Object -Character

There is also a words switched parameter that will return the number of words in the text file. It is used similarly to the character or line switched parameter. The command is shown here:

Get-Content C:\fso\a.txt | Measure-Object –Word

In the following figure, I use the Measure-Object cmdlet to count lines; then lines and characters; and finally lines, characters, and words. These commands illustrate combining the switches to return specific information.

Image of using Measure-Object to count

One really cool thing I can do with the Measure-Object cmdlet is to measure specific properties of the piped objects. For example, I can use the Get-ChildItem cmdlet to return fileinfo objects for all the text files in the folder. I can examine the length property and find out the minimum length of the files in the folder, the maximum length, the average size, and the total length of all files in the folder. This command and associated output are shown here:

PS C:\fso> Get-ChildItem -Filter *.txt | Measure-Object -Property length -Maximum -Minimum -Average -Sum

 

Count    : 66

Average  : 305903.833333333

Sum      : 20189653

Maximum  : 12534760

Minimum  : 0

Property : Length

 

If I want to, I can pipe the output to a table and create my own custom headings and output. In the following example, I display the average size of the files in kilobytes. I also define the format to omit decimal places:

PS C:\fso> Get-ChildItem -Filter *.txt | Measure-Object -Property length -Maximum -Minimum -Average -Sum | ft count, @{“Label”=”average size(KB)”;”Expression”={($_.average/1KB).tostring(0)}}

 

                                                      Count                      Average size(KB)

                                                      —–                        —————-

                                                         66                        299

 

Well, that is about all there to say for now. The Measure-Object cmdlet is one of my favorite cmdlets because it is easy to use and extremely flexible—an unbeatable combination in my book. What is your favorite cmdlet? Add a comment below and let me know. Until tomorrow, see ya.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

 

 

Author

The "Scripting Guys" is a historical title passed from scripter to scripter. The current revision has morphed into our good friend Doctor Scripto who has been with us since the very beginning.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • TR M

    Or is it the "grep -co" version? That is where is shows a count of all occurrences including multiple instances in a single line
    PS C:\> $Matches = Select-String -InputObject (Get-Content .\PS-Commands.txt) -Pattern "get" -AllMatches
    PS C:\> $Matches.Matches.Count493             (as opposed to 486 for the standard "grep -ci" type of command)
    I generated the test file by "Get-Command >PS-Commands.txt".
    **Weird but it works from the Powershell CLI but not the ISE. What gives with that?**

    Read more
  • TR M

    Or was it more of a grep count thing you wanted? I think I misread. Here is the “grep -c” version:
    PS C:\> Get-Content .\PS-Commands.txt | Select-String “get” | Measure-Object -Line