Display first/last N lines from file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
miskox
Posts: 576
Joined: 28 Jun 2010 03:46

Display first/last N lines from file

#1 Post by miskox » 27 Nov 2014 02:26

Hi all!

How can I display (or set an array of variables (for example x[cnt])) of first/last n lines from a .txt file?

viewtopic.php?f=3&t=3633 has a solution for reading all lines to variable.

One way would be to:
1. count the number of lines
2. sort in reverse (if data allows this - probably some files/data prevent this)
3. skip total_num_of_lines - N
4. display/process remaining lines

Another way:
In a loop (incrementing a counter). When counter reches N then we end the loop (which we know is hard to do) or we just keep it loooooping (without doing anything of course) until it ends. This would probably be good for display first N lines. For displaying last N lines sorting in reverse would probably needed.

But these to options probably would not be very efficient on big files.

Thanks.
Saso

npocmaka_
Posts: 513
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: Display first/last N lines from file

#2 Post by npocmaka_ » 27 Nov 2014 05:25

Here's a way with findstr

Code: Select all

@echo off
setlocal
 
rem ---------------------------
rem ------ arg parsing --------
rem ---------------------------
 
    if "%~1" equ "" goto :help
        for %%H in (/h -h /help -help) do (
                if /I "%~1" equ "%%H" goto :help
        )
        setlocal enableDelayedExpansion
            set "prev="
            for %%A in (%*) do (
                    if /I "!prev!" equ "-file" set file=%%~fsA
                    if /I "!prev!" equ "-begin" set begin=%%~A
                    if /I "!prev!" equ "-end" set end=%%A
                    set prev=%%~A
            )
        endlocal & (
                if "%file%" neq "" (set file=%file%)
                if "%begin%" neq "" (set /a begin=%begin%)
                if "%end%" neq "" (set /a end=%end%)
        )
 
rem -----------------------------
rem --- invalid cases check -----
rem -----------------------------
       
        if "%file%" EQU "" echo file not defined && exit /b 1
        if not exist "%file%"  echo file not exists && exit /b 2
        if not defined begin if not defined end echo neither BEGIN line nor END line are defined && exit /b 3
       
rem --------------------------
rem -- function selection ----
rem --------------------------
       
        if defined begin if %begin%0 LSS 0 for /F %%C in ('find /c /v "" ^<"%file%"')  do set /a lines_count=%%C
        if defined end if %end%0 LSS 0 if not defined lines_count for /F %%C in ('find /c /v "" ^<"%file%"')  do set lines_count=%%C
               
                rem -- begin only
        if not defined begin if defined end if %end%0 GEQ 0 goto :end_only
        if not defined begin if defined end if %end%0 LSS 0 (
                        set /a end=%lines_count%%end%+1
                        goto :end_only
                )
               
                rem -- end only
        if not defined end if defined begin if %begin%0 GEQ 0 goto :begin_only
        if not defined end if defined begin if %begin%0 LSS 0 (
                        set /a begin=%lines_count%%begin%+1
                        goto :begin_only
                )
                rem -- begin and end
        if %begin%0 LSS 0 if %end%0 LSS 0 (
                        set /a begin=%lines_count%%begin%+1
                        set /a end=%lines_count%%end%+1
                        goto :begin_end
                )
        if %begin%0 LSS 0 if %end%0 GEQ 0 (
                        set /a begin=%lines_count%%begin%+1
                        goto :begin_end
                )
        if %begin%0 GEQ 0 if %end%0 LSS 0 (
                        set /a end=%lines_count%%end%+1
                        goto :begin_end
                )
        if %begin%0 GEQ 0 if %end%0 GEQ 0 (
                        goto :begin_end
                )     
goto :eof
 
rem -------------------------
rem ------ functions --------
rem -------------------------
 
rem -----  single cases -----
 
:begin_only
        setlocal DisableDelayedExpansion
        for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
                set "line=%%L"
                for /F "delims=:" %%n in ("%%L") do (
                        if %%n GEQ %begin% (
                                setlocal EnableDelayedExpansion
                                set "text=!line:*:=!"
                                (echo(!text!)
                                endlocal
                        )
                )
        )
        endlocal
endlocal
goto :eof
 
:end_only
        setlocal disableDelayedExpansion
        for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
                set "line=%%L"
                for /F "delims=:" %%n in ("%%L") do (
                        IF %%n LEQ %end% (
                                setlocal EnableDelayedExpansion
                                set "text=!line:*:=!"
                                (echo(!text!)
                                endlocal
                        ) ELSE goto :break_eo
                )
        )
        :break_eo
        endlocal
endlocal
goto :eof
 
rem ---  end and begin case  -----
 
:begin_end
        setlocal disableDelayedExpansion
        if %begin% GTR %end% goto :break_be
        for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
                set "line=%%L"
                for /F "delims=:" %%n in ("%%L") do (
                    IF %%n GEQ %begin% IF %%n LEQ %end% (       
                        setlocal EnableDelayedExpansion
                        set "text=!line:*:=!"
                       (echo(!text!)
                        endlocal
                    ) ELSE goto :break_be                             
                )
        )
        :break_be
        endlocal
endlocal
goto :eof
rem ------------------
rem --- HELP ---------
rem ------------------
:help
    echo(
        echo %~n0 - dipsplays a lines of a file defined by -BEGIN and -END arguments passed to it
        echo(
        echo( USAGE:
        echo(
        echo %~n0  -file=file_to_process {-begin=begin_line ^| -end=end_line }
        echo or
        echo %~n0  -file file_to_process {-begin begin_line ^| -end end_line }
        echo(
        echo( if some of arguments BEGIN or END has a negative number it will start to count from the end of file
        echo(
        echo( http://ss64.org/viewtopic.php^?id^=1707
        echo(
goto :eof


or a less verbose way using FC and MORE:


Code: Select all

break>"%temp%\empty"&&fc "%temp%\empty" "<some_file>" /lb  <N_FirstLines> /t |more +4 | findstr /B /E /V "*****"|more  +<N_LastLines>

goldfish
Posts: 10
Joined: 31 Mar 2014 07:02

Re: Display first/last N lines from file

#3 Post by goldfish » 27 Nov 2014 05:44

depends on whether you can use tools especially designed for this purpose.
If you can, then you can try using tail /head.

Aacini
Expert
Posts: 1888
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Display first/last N lines from file

#4 Post by Aacini » 27 Nov 2014 07:36

You may do that in a very efficient way using my FindRepl.bat program, that is a Batch-JScript hybrid script. The /O:start:end switch allows to get a range of lines based on line numbers. As described in the documentation:

FindRepl.bat documentation wrote:2. Finding block of lines (/O switch)

Besides individual lines, FindRepl.bat program may also output blocks of lines around matching lines that are defined via two offsets with optional signs that will be added to the number of each matching line: FindRepl "Search" /O:s:e, or via an ending matching line: FindRepl "Start" /E:"End", or via any combination: FindRepl "Start" /E:"End" /O:s:e. The simplest way to output a block of lines is via a direct range of line numbers without Search part.

- Show from line 12 to line 34:

Code: Select all

< theFile.txt FindRepl /O:12:34

- Show the first 15 lines (head):

Code: Select all

< theFile.txt FindRepl /O:1:15

- Show the last 20 lines (tail):

Code: Select all

< theFile.txt FindRepl /O:-20

- Show both the first 15 lines and the last 20 lines (with line numbers):

Code: Select all

< theFile.txt FindRepl /V /O:16:-21 /N



For example, to store the first %cnt% lines in x array:

Code: Select all

set i=0
for /F "delims=" %%a in ('^< theFile.txt FindRepl /O:1:%cnt%') do (
   set /A i+=1
   set "x[!i!]=%%a!
)


Antonio

miskox
Posts: 576
Joined: 28 Jun 2010 03:46

Re: Display first/last N lines from file

#5 Post by miskox » 29 Nov 2014 03:54

Thank you all for your answers.

I like Aacini's version a lot - it is very quick.

I prefer not to use 3rd party programs if possible.

Again, thank you all.

Saso

Post Reply