<http://www.netikka.net/tsneti/info/tscmd064.htm>
Copyright © 2003-2012 by Prof. Timo Salmi  
Last modified Thu 2-Feb-2012 13:55:57

 
Assorted NT/2000/XP/.. CMD.EXE Script Tricks
From the html version of the tscmd.zip 1cmdfaq.txt file
To the Description and the Index
 

This page is edited from the 1cmdfaq.txt faq-file contained in my tscmd.zip command line interface (CLI) collection. That zipped file has much additional material, including a number of detached .cmd script files. It is recommended that you also get the zipped version as a companion.

Please see "The Description and the Index page" for the conditions of usage and other such information.



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

References/Comments: (If a Google message link fails try the links within the brackets.)
  Google Groups Apr 16 2006, 7:42 pm [M]
  Google Groups, Feb 1 2012, 12:49 pm
  Google Groups, Feb 2 2012, 1:50 pm