64} How to count the number of lines in a file, empty lines inclusive?
Assume the following LFN-type test file: "My test file.txt"
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4
line 6 Line 5 is empty!
line 7
line 8 &()[]{}^=;!'+,`~
line 9
First note that the following pure script will not solve the stated
problem.
@echo off & setlocal enableextensions
set myfile_=C:\_D\TEST\My test file.txt
for /f %%r in ('type "%myfile_%"') do set /a lineCount+=1
echo The number of lines is %lineCount%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
The number of lines is 8
A pure script solution counting also the empty lines
@echo off & setlocal enableextensions
::
:: The test file
set myfile_=C:\_D\TEST\My test file.txt
::
:: The counting
for /f "tokens=1 delims=:" %%a in ('
findstr
/n ".*" "%myfile_%"') do (
set lineCount=%%a)
::
echo The number of lines is %lineCount%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
The number of lines is 9
Another option (pointed out by Phil Robyn):
@echo off & setlocal enableextensions
::
:: The test file
set myfile_=C:\_D\TEST\My test file.txt
::
:: The counting
for /f %%a in ('
find /v /c "" ^< "%myfile_%"') do (
set lineCount=%%a)
::
echo The number of lines is %lineCount%
endlocal & goto :EOF
If there are several empty lines at the end of the file, the two
methods may not tally.
A
gawk solution to the task is very
similar and also quite simple and brief.
@echo off & setlocal enableextensions
::
:: The test file
set myfile_=C:\_D\TEST\My test file.txt
::
:: The counting
for /f %%a in ('
type "%myfile_%"
^|gawk "{printf \"%%s\n\",NR}"') do (
set lineCount=%%a)
::
echo The number of lines is %lineCount%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
The number of lines is 9
A Visual Basic Script aided command line script solution
@echo off & setlocal enableextensions
::
set myfile_=C:\_D\TEST\My test file.txt
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\tmp$$$.vbs
set cmd_=%temp%\tmp$$$.cmd
findstr "'%skip%VBS" "%~f0" > "%vbs_%"
::
:: Run it with Microsoft Windows Script Host Version 5.6
cscript //nologo "%vbs_%" < "%myfile_%" > "%cmd_%"
::
:: Call the command line script the script host built
call "%cmd_%"
::
:: Show the result
echo The number of lines in "%myfile_%" is %lines%
::
:: Clean up
for %%f in ("%vbs_%" "%cmd_%") do if exist %%f del %%f
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
i = 0 'VBS
Do While Not WScript.StdIn.AtEndOfStream 'VBS
i = i + 1 'VBS
str = WScript.StdIn.ReadLine 'VBS
Loop 'VBS
WScript.StdOut.WriteLine "@set lines=" & i 'VBS
The output will be
C:\_D\TEST>cmdfaq
The number of lines in "C:\_D\TEST\My test file.txt" is 9
Alternatively
@echo off & setlocal enableextensions
::
set myfile_=C:\_D\TEST\My test file.txt
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\tmp$$$.vbs
findstr "'%skip%VBS" "%~f0" > "%vbs_%"
::
:: Run it with Microsoft Windows Script Host Version 5.6
for /f "tokens=*" %%a in ('
cscript //nologo "%vbs_%" "%myfile_%"') do (
set lines=%%a)
for %%f in ("%vbs_%") do if exist %%f del %%f
::
:: Show the result
echo The number of lines in "%myfile_%" is %lines%
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
fileName = WScript.Arguments.Unnamed(0) 'VBS
Set FSO = CreateObject("Scripting.FileSystemObject") 'VBS
Set f = FSO.OpenTextFile(fileName, ForReading, True) 'VBS
n = 0 'VBS
Do While Not f.AtEndOfStream 'VBS
n = n + 1 'VBS
s = f.ReadLine 'VBS
Loop 'VBS
WScript.Echo n 'VBS
Consider a somewhat similar task:
'For example, I have a data file,
say "My test file.txt". I need to find the line numbers where
"START_OF_DATA" and "END_OF_DATA" are written.'
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4 START_OF_DATA
line 6 Line 5 is empty!
line 7 Hello world
line 8 END_OF_DATA
line 9 &()[]{}^=;!'+,`~
line10
@echo off & setlocal enableextensions
set filename_=C:\_D\TEST\My test file.txt
for /f "usebackq tokens=1 delims=:" %%a in (
`findstr /n "START_OF_DATA" "%filename_%"`) do (
set startDataNR_=%%a)
for /f "usebackq tokens=1 delims=:" %%a in (
`findstr /n "END_OF_DATA" "%filename_%"`) do (
set endDataNR_=%%a)
echo startDataNR_=%startDataNR_% endDataNR_=%endDataNR_%
endlocal & goto :EOF
The output will be
C:\_D\TEST>cmdfaq
startDataNR_=4 endDataNR_=8
Note one subtle catch, if the datafile contains empty lines. FINDSTR
will count them in (which is more logical), but, as we know, many batch
script operations will skip the empty lines. Thus in some cases, if one
uses the FINDSTR-generated information in the actual production batch,
the results might be out of synch. To demonstrate, consider
@echo off & setlocal enableextensions
set filename_=C:\_D\TEST\My test file.txt
for /f "usebackq tokens=1 delims=:" %%a in (
`type "%filename_%"`) do (
echo %%a)
endlocal & goto :EOF
The output will be (note the missing fifth line)
C:\_D\TEST>cmdfaq
line 1
line 2 &()[]{}^=;!'+,`~
line 3 <>
line 4 START_OF_DATA
line 6 Line 5 is empty!
line 7 Hello world
line 8 END_OF_DATA
line 9 &()[]{}^=;!'+,`~
line10
What to do if you for some reason
need to
ignore the empty lines. It gets more complicated, but still is doable.
Let's, however, only consider the END_OF_DATA for brevity.
@echo off & setlocal enableextensions
enabledelayedexpansion
set filename_=C:\_D\TEST\My test file.txt
set lineCount_=
for /f "usebackq tokens=1 delims=:" %%a in (
`type "%filename_%"`) do (
set /a lineCount=!lineCount!+1
echo "%%a"|find "END_OF_DATA">nul
if !errorlevel! EQU 0 set endDataNR_=!lineCount!)
echo lineCount=%lineCount% endDataNR_=%endDataNR_%
endlocal & goto :EOF
The output will be (note the difference in the outcome)
C:\_D\TEST>cmdfaq
lineCount=9 endDataNR_=7