Discussion:
Tail command to see last few lines
(too old to reply)
Timo Salmi
2005-05-08 05:09:19 UTC
Permalink
The batch code below does the same and requires WSH which ships
with all flavours of Windows since Windows 98 (or SE). :: Create a
temp. VBS file that shows the last 10 lines of a text file
ECHO content = Split(file.ReadAll, vbCrLf, -1, 1)>>%TEMP%.\_.VBS
Scripting Runtime Library documentation: "For large files,
using the ReadAll method wastes memory resources. Other techniques
should be used to input a file, such as reading a file line by line."

Here is an alternative, written for XP

A Visual Basic Script (VBScript) aided command line script version
of "tail"
@echo off & setlocal enableextensions
::
:: Make a test file
for %%i in (1 2 3 4 5 6) do echo This is line %%i>>MyFile.txt
echo.>>MyFile.txt
for %%i in (8 9 10 11 12) do echo This is line %%i>>MyFile.txt
::
:: Build a Visual Basic Script
set skip=
set vbs_=%temp%\vtail.vbs
findstr "'%skip%VBS" "%~f0" > %vbs_%
::
:: Run the script with Microsoft Windows Script Host Version 5.6
cscript //nologo %vbs_% "MyFile.txt" 3
::
:: Clean up
for %%f in (%vbs_% MyFile.txt) do del %%f
endlocal & goto :EOF
'
'.......................................................
'The Visual Basic Script
'
' Define some constant
Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
Dim fileName, FSO, f, i, n, nArg, s 'VBS
'
' Check the right usage
nArg = WScript.Arguments.Count 'VBS
If (nArg = 0) Or (nArg > 2) Then 'VBS
s = "Usage: cscript //nologo " 'VBS
s = s & WScript.ScriptName 'VBS
s = s & " fileName [NumberOfLinesFromEnd]" 'VBS
WScript.Echo s 'VBS
WScript.Quit 'VBS
End If 'VBS
'
' Get the arguments, fileName and tailLines
fileName=WScript.Arguments.Unnamed(0) 'VBS
If WScript.Arguments.Count > 1 Then 'VBS
tailLines = CLng(WScript.Arguments.Unnamed(1)) 'VBS
Else 'VBS
tailLines = 10 'VBS
End If 'VBS
'
' Check that the file exists
Set FSO=CreateObject("Scripting.FileSystemObject") 'VBS
if not FSO.FileExists(fileName) Then 'VBS
WScript.Echo "File " & fileName & " Not Found" 'VBS
WScript.Quit 'VBS
End If 'VBS
'
' Calculate the number of lines
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
'
' Output the tail part of the file
Set f = FSO.OpenTextFile(fileName, ForReading, True) 'VBS
i = 0 'VBS
Do While Not f.AtEndOfStream 'VBS
i = i + 1 'VBS
s = f.ReadLine 'VBS
If i > n - tailLines Then WScript.Echo s 'VBS
Loop 'VBS

The output will be
C:\_D\TEMP>cmdfaq
This is line 10
This is line 11
This is line 12

All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:***@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip
William Allen
2005-05-08 07:39:18 UTC
Permalink
"Timo Salmi" wrote in message
Post by Timo Salmi
The batch code below does the same and requires WSH which ships
with all flavours of Windows since Windows 98 (or SE). :: Create a
temp. VBS file that shows the last 10 lines of a text file
ECHO content = Split(file.ReadAll, vbCrLf, -1, 1)>>%TEMP%.\_.VBS
Scripting Runtime Library documentation: "For large files,
using the ReadAll method wastes memory resources. Other techniques
should be used to input a file, such as reading a file line by line."
Here is an alternative, written for XP
...snip
Post by Timo Salmi
Do While Not f.AtEndOfStream 'VBS
...snip
Post by Timo Salmi
Do While Not f.AtEndOfStream 'VBS
Assuming that the file consists of a large number of lines, but
that the number of tail lines to be output is relatively small, it's
more efficient to read the file once only. During the read, instead
of counting the lines, you push each line into a small, rotating
stack held in a (size=TailLines) dynamic array.

At the EndOfStream, you pop the stack array to echo the tail.

Leaving out the checking routines for arguments/file-existence,
this fragment of VBS code shows the rotating stack algorithm
(assumes filename=first argument TailLines=second argument):

Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
Set Args=WScript.Arguments
fileName=Args(0):tail=Args(1)
Set fso=CreateObject("Scripting.FileSystemObject")
Set f=fso.OpenTextFile(fileName, 1)
n=0:ReDim line(tail)
Do While Not f.AtEndOfStream
n=(n+1) Mod tail
line(n)=f.ReadLine
Loop
For j=1 To tail
n=(n+1) Mod tail
wscript.echo line(n)
Next

====End cut-and-paste (omit this line)
For study/demo use. Cut-and-paste as VBScript .VBS plain-text file.
Batch file troubleshooting: http://www.allenware.com/find?UsualSuspects

============Screen capture Windows 95
C:\WORK>type file.txt
one
two
three
four
five
six
seven
eight
nine
ten

C:\WORK>cscript//nologo demo.vbs file.txt 4
seven
eight
nine
ten

C:\WORK>
============End screen capture

--
William Allen
Free interactive Batch Course http://www.allenware.com/icsw/icswidx.htm
Batch Reference with examples http://www.allenware.com/icsw/icswref.htm
Header email is rarely checked. Contact us at http://www.allenware.com/
Todd Vargo
2005-05-09 00:04:45 UTC
Permalink
Post by William Allen
Leaving out the checking routines for arguments/file-existence,
this fragment of VBS code shows the rotating stack algorithm
Lines that don't begin with two spaces have wrapped accidentally
====Begin cut-and-paste (omit this line)
Set Args=WScript.Arguments
fileName=Args(0):tail=Args(1)
Set fso=CreateObject("Scripting.FileSystemObject")
Set f=fso.OpenTextFile(fileName, 1)
n=0:ReDim line(tail)
Do While Not f.AtEndOfStream
n=(n+1) Mod tail
line(n)=f.ReadLine
Loop
For j=1 To tail
n=(n+1) Mod tail
wscript.echo line(n)
Next
Nice code, but it needs to verify that 'tail' has been reached rather than
assume the file has more lines then the number provided. The following
condition will satisfy that need.

If Not line(n)=vbEmpty Then wscript.echo line(n)

--
Todd Vargo (double "L" to reply by email)

Continue reading on narkive:
Loading...