CMD.EXE batch script to display last 10 lines from a txt file
Asked Answered
I

10

18

Any ideas how to echo or type the last 10 lines of a txt file?

I'm running a server change log script to prompt admins to state what they're doing, so we can track changes. I'm trying to get the script to show the last 10 entries or so to give an idea of what's been happening recently. I've found a script that deals with the last line, as shown below, but can't figure out what to change in it to display the last 10 lines. Script:

@echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (c:\log09.txt) do (
set var=%%a
)
echo !var!

Example of log file:

06/02/2009, 12:22,Remote=Workstation-9,Local=,
mdb,bouncing box after updates,CAS-08754,
=================
07/02/2009, 2:38,Remote=,Local=SERVER1,
mdb,just finished ghosting c drive,CAS-08776,
=================
07/02/2009, 3:09,Remote=,Local=SERVER1,
mdb,audit of server,CAS-08776,

Any thoughts? The script works great, just need it to pipe more lines to the screen.

Inaccuracy answered 7/2, 2009 at 5:4 Comment(1)
#188087Simulacrum
C
19

Hopefully this will save Joel's eyes :)

@echo OFF

:: Get the number of lines in the file
set LINES=0
for /f "delims==" %%I in (data.txt) do (
    set /a LINES=LINES+1
)

:: Print the last 10 lines (suggestion to use more courtsey of dmityugov)
set /a LINES=LINES-10
more +%LINES% < data.txt
Copycat answered 7/2, 2009 at 15:47 Comment(5)
I believe you can use more +n command in your example, which starts printing the file at line nDira
This isn't last 10 lines. It's all lines since line number 10.Deerdre
@stupid_idiot, are you sure? This works under Windows 7, both 64 and 32 bit consoles.Copycat
@PatrickCuff, oh dammit, sorry, you're right, once again I win the pie.Deerdre
You probably wants to add if %LINES% lss 0 set LINES=0 before more +%LINES% < data.txt, in case the file has less than 10 lines.Abelabelard
S
12

This answer combines the best features of already existing answers, and adds a few twists.

The solution is a simple batch implementation of the tail command.

The first argument is the file name (possibly with path information - be sure to enclose in quotes if any portion of path contains spaces or other problematic characters).

The second argument is the number of lines to print.

Finally any of the standard MORE options can be appended: /E /C /P /S /Tn. (See MORE /? for more information).

Additionally the /N (no pause) option can be specified to cause the output to be printed continuosly without pausing.

The solution first uses FIND to quickly count the number of lines. The file is passed in via redirected input instead of using a filename argument in order to eliminate the printout of the filename in the FIND output.

The number of lines to skip is computed with SET /A, but then it resets the number to 0 if it is less than 0.

Finally uses MORE to print out the desired lines after skipping the unwanted lines. MORE will pause after each screen's worth of lines unless the output is redirected to a file or piped to another command. The /N option avoids the pauses by piping the MORE output to FINDSTR with a regex that matches all lines. It is important to use FINDSTR instead of FIND because FIND can truncate long lines.

:: tail.bat File Num [/N|/E|/C|/P|/S|/Tn]...
::
::   Prints the last Num lines of text file File.
::
::   The output will pause after filling the screen unless the /N option
::   is specified
::
::   The standard MORE options /E /C /P /S /Tn can be specified.
::   See MORE /? for more information
::
@echo OFF
setlocal
set file=%1
set "cnt=%~2"
shift /1
shift /1
set "options="
set "noPause="
:parseOptions
if "%~1" neq "" (
  if /i "%~1" equ "/N" (set noPause=^| findstr "^") else set options=%options% %~1
  shift /1
  goto :parseOptions
)
for /f %%N in ('find /c /v "" ^<%file%') do set skip=%%N
set /a "skip-=%cnt%"
if %skip% lss 0 set skip=0
more +%skip% %options% %file% %noPause%
Selie answered 12/2, 2012 at 19:32 Comment(10)
+1 - find /c /v ""... is MUCH faster than find /v /c "%%$%!"... when the file is very largeChambermaid
How to use /N here. I am trying to use this for tail -f kind of functionality. Does /N option does that?Disserve
@AbibullahRahamathulah - No, there is no equivalent to the tail -f option. The \N option simply causes the output to flow continuously without pause. Without the \N option, the output pauses each time the screen is filled.Selie
@dbenham, Yes I understood that now. I have started using the tail.exe and its working. Thanks for your response.Disserve
For some reason this script counted only 5442138 lines when the file was actually 44479179 lines long. I fixed it by changing the for loop line to read: for /f %%N in ('type %file% ^| find /c /v ""') do set skip=%%NAmbiguity
After 65246 lines (of 100000) or 965500 lines (of 1000000) with the /N flag, the command prompt stops, but the command doesn't complete. Pressing enter at this point shows one line, but pressing space allows the command to continue to the end. I'm not enough of a batch wizard to figure out what's going on here.Consentaneous
@Consentaneous - That is a known behavior/limitation of the MORE command. So you will have to use some other solution if you are dealing with a large file.Selie
I figured, but what exactly is the behavior here?Consentaneous
@Consentaneous - I've never seen any official documentation, nor have I tried to quantify the exact behavior. I've just seen multiple posts that describe problems similar to what you are getting. Normally MORE will not pause when output is piped. But if the number of lines exceeds a threshold around 64K (not sure of the exact number), then it pauses.Selie
Strange. Stranger yet that with 1 million lines, it freezes 96% of the way through.Consentaneous
R
10

You should probably just find a good implementation of tail. But if you really really insist on using CMD batch files and want to run on any NT machine unmolested, this will work:

@echo off
setLocal EnableDelayedExpansion
for /f "tokens=* delims= " %%a in (c:\tmp\foo.txt) do (
set var9=!var8!
set var8=!var7!
set var7=!var6!
set var6=!var5!
set var5=!var4!
set var4=!var3!
set var3=!var2!
set var2=!var1!
set var1=!var!
set var=%%a
)
echo !var9!
echo !var8!
echo !var7!
echo !var6!
echo !var5!
echo !var4!
echo !var3!
echo !var2!
echo !var1!
echo !var!
Rigid answered 7/2, 2009 at 6:30 Comment(4)
Hm, that's the kind of straightforward way I never really consider with batch files. But yes, it nibbles away at the eyes.Nicobarese
Nice one… but will output blank lines if input file is less than 10 lines long. And… why delims={space} not delims={nothing}?Reverberatory
This is an interesting brute force approach that can work nicely if the files are cooperative. However, another minor gotcha is that the echo commands may not always print what you expect them to print: since the commands are "eval"ed, any lines beginning with "/?" will display the echo help message instead of the data.Introject
@MattiasAndersson That gotcha is avoided with echo., i.e. echo.!varn! will avoid that problem.Blether
T
4

There are several windows implementations of the tail command. It should be exactly what you want.

This one sounds particularly good: http://malektips.com/xp_dos_0001.html

They range from real-time monitoring to the last x lines of the file.

Edit: I noticed that the included link is to a package It should work, but here are some more versions:

http://www.lostinthebox.com/viewtopic.php?f=5&t=3801 http://sourceforge.net/projects/tailforwin32

Tanganyika answered 7/2, 2009 at 5:11 Comment(0)
H
4

If file is too large it can take too long to get count of lines another way is to use find and pass it a nowhere string

$find /v /c "%%$%!" yourtextfile.txt

this would result an output like this

$---------- yourtextfile.txt: 140

then you can parse output using for like this

$for /f "tokens=3" %i in ('find /v /c "%%$%!" tt.txt') do set countoflines=%i

then you can substract ten lines from the total lines

Hagerman answered 16/3, 2009 at 23:14 Comment(0)
L
4

After trying all of the answers I found on this page none of them worked on my file with 15539 lines.

However I found the answer here to work great. Copied into this post for convenience.

@echo off
for /f %%i in ('find /v /c "" ^< C:\path\to\textfile.txt') do set /a lines=%%i
set /a startLine=%lines% - 10
more /e +%startLine% C:\path\to\textfile.txt

This code will print the last 10 lines in the "C:\path\to\textfile.txt" file.

Credit goes to OP @Peter Mortensen

Lesbian answered 14/8, 2015 at 19:17 Comment(0)
P
3

using a single powershell command:

powershell -nologo "& "Get-Content -Path c:\logFile.log -Tail 10"

applies to powershell 3.0 and newer

Prate answered 18/3, 2015 at 13:26 Comment(3)
You could also create a batch file named TAIL.CMD with this code: powershell -nologo "& "Get-Content -Path %1 -Tail 10"Macon
Why go through the pain of calling PowerShell from cmd.exe? Just use PowerShell interactively instead of cmd.exe and type the command.Ivoryivorywhite
the original question asked for a batch script, so i framed my reply as such.Prate
M
1

I agree with "You should use TAIL" answer. But it does not come by default on Windows. I suggest you download the "Windows 2003 Resource Kit" It works on XP/W2003 and more.

If you don't want to install on your server, you can install the resource kit on another machine and copy only TAIL.EXE to your server. Usage is sooooo much easier.

C:\> TAIL -10 myfile.txt
Macon answered 23/11, 2012 at 15:52 Comment(0)
C
1

Here's a utility written in pure batch that can show a lines of file within a given range.To show the last lines use (here the script is named tailhead.bat):

call tailhead.bat -file "file.txt" -begin -10
Choleric answered 20/1, 2016 at 22:13 Comment(0)
L
0

Any ideas how to echo or type the last 10 lines of a txt file?

The following 3-liner script will list the last n lines from input file. n and file name/path are passed as input arguments.

# Script last.txt
var str file, content ; var int n, count
cat $file > $content ; set count = { len -e $content } - $n
stex -e ("["+makestr(int($count))) $content

The script is in biterscripting. To use, download biterscripting from http://www.biterscripting.com , save this script as C:\Scripts\last.txt, start biterscripting, enter the following command.

script last.txt file("c:\log09.txt") n(10)

The above will list last 10 lines from file c:\log09.txt. To list last 20 lines from the same file, use the following command.

script last.txt file("c:\log09.txt") n(20)

To list last 30 lines from a different file C:\folder1\somefile.log, use the following command.

script last.txt file("C:\folder1\somefile.log") n(30)

I wrote the script in a fairly generic way, so it can be used in various ways. Feel free to translate into another scripting/batch language.

Lipography answered 13/7, 2009 at 20:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.