npocmaka
Probably there are other implementations of tail , but I couldn't find:
Code: Select all
@echo off
setlocal
if "%~2" equ "" echo USAGE: %~n0 file lines && exit /b 2
if not exist "%~1" echo file does not exists && exit /b 1
set /a lines=%~2
setlocal enableDelayedExpansion
for /f "tokens=1,2* delims=:" %%L in ('findstr /R /N "^" "%~1"') do (
if %%L LEQ %lines% (
endlocal
echo/ %%M
) else (
goto :endfor
)
)
:endfor
endlocal
endlocal
Last edited by npocmaka (23 May 2013 13:08)
----------------------------
#2 22 May 2013 07:43
jeb
Hi npocmaka,
Disable delayed expansion and this problem is gone.npocmaka wrote:
And !s are not processed well.
BUT there are still some others.
You strip all leading colons from any line.
With "echo/ %%M" you prefix each line with a space and it fails for a line containing a single "?",
better use "echo(%%M" here.
You could use the "set/p" technic to read the lines or the FOR/F delayed toggling technic.
jeb
Last edited by jeb (22 May 2013 07:46)
----------------------------
#3 22 May 2013 08:37
npocmaka
Thanks!
improved:
Code: Select all
@echo off
setlocal
if "%~2" equ "" echo USAGE: %~n0 file lines && exit /b 2
if not exist "%~1" echo file does not exists && exit /b 1
set /a lines=%~2
setlocal enableDelayedExpansion
for /f "tokens=1,2* delims=:" %%L in ('findstr /R /N "^" "%~1"') do (
if %%L LEQ %lines% (
setlocal disableDelayedExpansion
echo\%%M
endlocal
) else (
goto :endfor
)
)
:endfor
endlocal
endlocal
And the possibility of breaking parentheses context makes me sick .Prefer to use echo? or echo\ instead of echo(
Will try another implementations later...
----------------------------
#4 22 May 2013 08:53
jeb
Hmmm, why are you toggling delayed expansion? Your code don't need it at all.
No. echo( never breaks the parentheses context.npocmaka wrote:
And the possibility of breaking parentheses context makes me sick .Prefer to use echo? or echo\ instead of echo(
But echo\ fails with "..\..\..\windows\system32\calc.exe" in %%M
Code: Select all
@echo off
setlocal DisableDelayedExpansion
set /a lines=%~2
for /F "delims=" %%L in ('findstr /R /N "^" "%~1"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
if %%n LEQ %lines% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break
)
)
:break
#5 22 May 2013 09:06
npocmaka
great
Didn't find way to break it.And it can be easy enhanced to show the lines from the end...
----------------------------
#6 22 May 2013 09:32
npocmaka
and the enhanced edition (if the number of lines is negative shows the last lines):
Code: Select all
@echo off
if "%~2" equ "" echo USAGE: %~n0 file lines && exit /b 2
if not exist "%~1" echo file does not exists && exit /b 1
setlocal DisableDelayedExpansion
set /a lines=%~2
if %lines% LSS 0 (
for /F %%C in ('findstr /R /N "^" "%~1" ^| find /C ":"') do set line_count=%%C && goto :backward
)
for /F "delims=" %%L in ('findstr /R /N "^" "%~1"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
if %%n LEQ %lines% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break
)
)
:break
endlocal
exit /b 0
:backward
set /a start_line=%line_count%%lines%
for /F "delims=" %%L in ('findstr /R /N "^" "%~1"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
if %%n GEQ %start_line% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
)
)
)
endlocal
exit /b 0
----------------------------
#7 22 May 2013 09:37
foxidrive
On recent Windows this works - 65K lines generates a pause but that's the only issue.
for line 120 and onward
Code: Select all
More +120 "file.txt"
#8 22 May 2013 12:18
dbenham
Actually the above will pause after every screen unless the MORE output is either redirected or piped. But I believe you are correct that even piped or redirected output will pause at some point.foxidrive wrote:
On recent Windows this works - 65K lines generates a pause but that's the only issue.
for line 120 and onward
Code: Select all
More +120 "file.txt"
Unfortunately the pause is not the only issue.
MORE converts TABs into a series of SPACEs, and there is no way to prevent MORE from doing that. That may or may not be a problem.
Dave Benham
----------------------------
#9 22 May 2013 12:37
foxidrive
Confirmed fwiw. That's a bugger. Win 8 converts a tab at the start of a line into 8 spaces.dbenham wrote:
MORE converts TABs into a series of SPACEs, and there is no way to prevent MORE from doing that. That may or may not be a problem.
There are so many gotcha's in batch - I think that's why we like it.
----------------------------
#10 23 May 2013 13:12
npocmaka
First release candidate .More I look at this more it looks like something that can be simplified :
(it accepts two arguments BEGIN and END for the lines beyond the file.If some of arguments is negative it will start from the end).Still not extensive tested.
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 ('findstr /R /N "^" "%file%" ^| find /C ":"') do set /a lines_count=%%C
if defined end if %end%0 LSS 0 if not defined lines_count for /F %%C in ('findstr /R /N "^" "%file%" ^| find /C ":"') do set lines_count=%%C
if not defined begin if defined end if %end%0 GEQ 0 goto :positive_end_only
if not defined begin if defined end if %end%0 LSS 0 goto :negative_end_only
if not defined end if defined begin if %begin%0 GEQ 0 goto :positive_begin_only
if not defined end if defined begin if %begin%0 LSS 0 goto :negative_begin_only
if %begin%0 LSS 0 if %end%0 LSS 0 goto :negative_negative
if %begin%0 LSS 0 if %end%0 GEQ 0 goto :negative_positive
if %begin%0 GEQ 0 if %end%0 LSS 0 goto :positive_negative
if %begin%0 GEQ 0 if %end%0 GEQ 0 goto :positive_positive
goto :eof
rem -------------------------
rem ------ functions --------
rem -------------------------
rem ----- single cases -----
:positive_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
:negative_begin_only
setlocal DisableDelayedExpansion
set /a begin_line=%lines_count%%begin%+1
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
if %%n GEQ %begin_line% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
)
)
)
endlocal
endlocal
goto :eof
:positive_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_peo
)
)
:break_peo
endlocal
endlocal
goto :eof
:negative_end_only
setlocal disableDelayedExpansion
set /a end_line=%lines_count%%end%+1
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
IF %%n LEQ %end_line% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_neo
)
)
:break_neo
endlocal
endlocal
goto :eof
rem --- end and begin cases -----
:negative_negative
setlocal disableDelayedExpansion
set /a end_line=%lines_count%%end%+1
set /a begin_line=%lines_count%%begin%+1
if %begin_line% GTR %end_line% goto :break_nn
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
IF %%n GEQ %begin_line% (
IF %%n LEQ %end_line% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_nn
)
)
)
:break_nn
endlocal
endlocal
goto :eof
:negative_positive
setlocal disableDelayedExpansion
set /a begin_line=%lines_count%%begin%+1
if %begin_line% GTR %end% goto :break_nn
for /F "delims=" %%L in ('findstr /R /N "^" "%file%"') do (
set "line=%%L"
for /F "delims=:" %%n in ("%%L") do (
IF %%n GEQ %begin_line% (
IF %%n LEQ %end% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_np
)
)
)
:break_np
endlocal
endlocal
goto :eof
:positive_negative
echo oioioi
setlocal disableDelayedExpansion
set /a end_line=%lines_count%%end%+1
if %begin% GTR %end_line% goto :break_nn
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_line% (
setlocal EnableDelayedExpansion
set "text=!line:*:=!"
(echo(!text!)
endlocal
) ELSE goto :break_pn
)
)
)
:break_pn
endlocal
endlocal
goto :eof
:positive_positive
setlocal disableDelayedExpansion
if %begin% GTR %end% goto :break_nn
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_pp
)
)
)
:break_pp
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_libe ^| -end=end_line }
echo or
echo %~n0 -file file_to_process {-begin begin_libe ^| -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
goto :eof
----------------------------
#11 29 May 2013 09:42
npocmaka
And here is a little bit improved version plus version that uses FOR /F - both are fairly the same. The second version should be faster , but i didn't make tests yet.Soon will create also SET /P version and will think about performance improvements (if it's possible).Still both versions set one additional empty line at the end.Will be glad to hear/red any feedback
FINDSTR version
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
FOR /Fversion
@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 enableDelayedExpansion
set counter=0
for /f "usebackq delims=" %%L in ("%file%") do (
set /a counter=!counter!+1
if !counter! GEQ %begin% (
setlocal disableDelayedExpansion
(echo(%%L)
endlocal
)
)
endlocal
goto :eof
:end_only
setlocal enableDelayedExpansion
set counter=0
for /f "usebackq delims=" %%L in ("%file%") do (
set /a counter=!counter!+1
if !counter! LEQ %end% (
setlocal disableDelayedExpansion
(echo(%%L)
endlocal
) else goto :break_eo
)
:break_eo
endlocal
goto :eof
rem ---- begin and end ---
:begin_end
setlocal enableDelayedExpansion
if %begin% GTR %end% goto :break_be
set counter=0
for /f "usebackq delims=" %%L in ("%file%") do (
set /a counter=!counter!+1
IF !counter! GEQ %begin% IF !counter! LEQ %end% (
setlocal disableDelayedExpansion
(echo(%%L)
endlocal
) else goto :break_be
)
:break_be
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
#12 17 Jul 2013 20:39
npocmaka
just a way with a less code to show the first lines of a file:
Code: Select all
@echo off
break>"%temp%\empty"
rem
rem fc "<some_file>" "%temp%\empty" /lb <numbers> /t | find /v "*****" | more +1
rem for /f "skip=3 eol=* delims=" %%L in ('fc "%temp%\empty" "<some_file>" /lb<lines_to_show> /t') do (echo(%%L)
rem
fc "%temp%\empty" "<some_file>" /lb <lines_to_show> /t |more +4 | findstr /B /E /V "*****"
rem and a line counter
for /f "skip=5 eol=* delims=: " %%N in ('fc %temp%\empty shiftt.bat /a /n') do (echo(%%N)