Note: If all you need is the line count of a single input file, a simple solution (which loads the whole file into memory) is, e.g., (gc file.txt).Count
(gc
is a built-in alias for Get-Content
).
Faster version: (gc -ReadCount 0 file.txt).Count
From cmd.exe
(the Command Prompt / a batch file), which is obsolescent:
From PowerShell, you have two options:
- Option A (suboptimal): Use the accepted answer too, with a small tweak:
find --% /c /v "" "C:\inputdirectory\P*"
Note: --%
, the stop-parsing symbol, tells PowerShell to pass subsequent arguments through as-is to the target program (after expanding cmd
-style environment-variable references such as %USERNAME%
, if any).
In the case at hand, this prevents PowerShell from parsing ""
and - mistakenly - neglecting to pass it through to the external target program (find.exe
).
For a summary of PowerShell's highly problematic handling of quotes when calling external programs, see this answer.
Output from the above find.exe
command - and, indeed, any external program, is just text, and in this case it looks something like this:
---------- PFILE1.TXT: 42
---------- PFILE2.TXT: 666
...
While this output is easy to grasp for a human observer, it makes subsequent programmatic processing cumbersome, because text parsing is required.
Using a PowerShell-native command (cmdlet), as described below, offers more flexibility, because PowerShell commands typically emit objects with typed properties, which greatly facilitates subsequent processing.
- Option B (preferred): Use PowerShell's own
Measure-Object
cmdlet with the -Line
switch:
Note: While this command is more verbose than the find
solution, it ultimately offers more flexibility due to outputting objects with typed properties, which greatly facilitates subsequent processing; additionally, PowerShell's sophisticated output-formatting system offers user-friendly default representations.
Get-Item -Path "C:\inputdirectory\P*" -PipelineVariable file | ForEach-Object {
Get-Content -LiteralPath $file |
Measure-Object -Line |
Select-Object @{ Name='File'; Expression={ $file } }, Lines
}
The above outputs objects that have a .File
and .Lines
property each, which PowerShell prints as follows by default:
File Lines
---- -----
C:\inputdirectory\Pfile1.txt 42
C:\inputdirectory\Pfile2.txt 666
...
In addition to a nicer presentation of the output, the object-oriented nature of the output makes it easy to programmatically process the results.
For instance, if you wanted to limit the output to those files whose line count is 100
or greater, pipe to the following Where-Object
call to the above command:
... | Where-Object Lines -ge 100
If you (additionally) wanted to sort by highest line count first, pipe to the Sort-Object
cmdlet:
... | Sort-Object -Descending Lines