PowerShell Measure-Object Count Lines in File

PowerShell Measure-Object Count Lines in File

PowerShell Tips Editor 4 min read
PowerShell Measure-Object Count Lines in File

How many records are in this CSV? How large is this log file in lines? Answering these questions quickly is something every sysadmin needs. PowerShell count lines in file is a single pipeline: Get-Content piped to Measure-Object. This post expands on the basic pattern to cover counting words, characters, matching lines, and handling large files without loading them entirely into memory.

Quick Answer / TL;DR

Run (Get-Content -Path C:\file.txt | Measure-Object -Line).Lines to count lines. For large files, use [System.IO.File]::ReadAllLines() or a StreamReader to avoid loading gigabytes into memory.

Count Lines with Measure-Object

Measure-Object with -Line counts the number of string objects it receives. Piping Get-Content output into it counts lines in the file. The result is an object — access the count via the .Lines property.

# Count lines in a file
$lineCount = (Get-Content -Path C:\Logs\app.log | Measure-Object -Line).Lines
Write-Host "Line count: $lineCount"

# One-liner
(Get-Content C:\Data\users.csv | Measure-Object -Line).Lines
Line count: 4827

Count Words in a File

Measure-Object -Word counts whitespace-delimited tokens across all lines. Pass the file content as strings — each line is counted for words. Use -Line -Word -Character together for a complete word processor-style stats report.

# Count words in a file
$stats = Get-Content -Path C:\Docs\report.txt | Measure-Object -Word
Write-Host "Words: $($stats.Words)"

# Full stats: lines, words, characters
$full = Get-Content C:\Docs\report.txt | Measure-Object -Line -Word -Character
$full | Select-Object Lines, Words, Characters

Count Characters in a File

Measure-Object -Character counts all characters in all lines. Note that the newline characters themselves are stripped by Get-Content, so the count may differ slightly from a raw byte count of the file. Use -IgnoreWhiteSpace to count non-whitespace characters only.

# Count characters (excluding newlines stripped by Get-Content)
$charCount = (Get-Content C:\Scripts\deploy.ps1 | Measure-Object -Character).Characters
Write-Host "Character count: $charCount"

# Count only non-whitespace characters
$nonWS = (Get-Content C:\Scripts\deploy.ps1 | Measure-Object -Character -IgnoreWhiteSpace).Characters
Write-Host "Non-whitespace characters: $nonWS"

Count Lines Matching a Pattern

Combine Select-String with Measure-Object to count lines matching a regex or literal string. This is the PowerShell equivalent of grep -c.

# Count error lines in a log
$errorCount = (Select-String -Path C:\Logs\app.log -Pattern '\[ERROR\]' | Measure-Object).Count
Write-Host "Error lines: $errorCount"

# Count lines containing a specific IP
$ipCount = (Get-Content C:\Logs\firewall.log |
    Where-Object { $_ -match '192\.168\.1\.' } |
    Measure-Object -Line).Lines
Write-Host "Lines with 192.168.1.x: $ipCount"

Count Lines Across Multiple Files

Pass multiple files to Get-Content using Get-ChildItem and a pipeline. Each file’s lines are counted separately, or group them together for a total count.

# Count lines per file
Get-ChildItem -Path C:\Logs -Filter '*.log' | ForEach-Object {
    $count = (Get-Content $_.FullName | Measure-Object -Line).Lines
    [PSCustomObject]@{
        File  = $_.Name
        Lines = $count
        SizeMB = [math]::Round($_.Length / 1MB, 2)
    }
} | Sort-Object Lines -Descending | Format-Table -AutoSize

# Total line count across all files
$total = Get-ChildItem C:\Logs -Filter '*.log' |
    Get-Content | Measure-Object -Line
Write-Host "Total lines across all logs: $($total.Lines)"

Efficient Line Count Without Loading All Lines

For large files (hundreds of megabytes or gigabytes), Get-Content loads every line into memory, which is slow and consumes significant RAM. Use [System.IO.File]::ReadAllLines() for moderate files, or a StreamReader for maximum efficiency on very large files.

# Fast: ReadAllLines — moderate files
$lineCount = [System.IO.File]::ReadAllLines('C:\Logs\large.log').Count
Write-Host "Lines: $lineCount"

# Fastest: StreamReader — minimal memory, works on any size file
$reader = [System.IO.StreamReader]::new('C:\Logs\huge.log')
$count  = 0
while ($reader.ReadLine() -ne $null) { $count++ }
$reader.Close()
Write-Host "Line count: $count"

Common Errors and Fixes

  • Get-Content loads whole file into memory — use StreamReader for huge files. A 2 GB log file loaded with Get-Content consumes 2+ GB of RAM and takes minutes. Use StreamReader instead — it reads one line at a time and counts without loading anything into memory beyond the current line.
  • Empty last line may inflate count by one. Some text files end with a trailing newline, causing Get-Content to return one extra empty string at the end. If exact counts matter, filter empty lines: Get-Content file.txt | Where-Object { $_ } | Measure-Object -Line.

Related Cmdlets / See Also

Wrapping Up

Get-Content | Measure-Object -Line handles the common case with one pipeline. For pattern-based counting, add Where-Object or Select-String before Measure-Object. For files over a few hundred megabytes, switch to StreamReader to keep memory usage and execution time reasonable.

Send-Item -To