Wellidontcare
Wellidontcare

Reputation: 11

How do I make a batchscript that displays only the last line of a textfile?

this might have already been answered before but I couldn't find anything on that topic. Im trying to make a chat messenger in batch and for that I need to display the last line of a textfile. Here's what I tried (not very elegant):

@echo off
FOR /F %%x in (address.txt) DO set address=%%x
:A
IF NOT EXIST "%address%" GOTO A
GOTO B
:B
SET skipcount=1
:C
FOR /f "skip=%skipcount%" %%m in (%address%) DO ECHO %%m
SET m1=%%m
:D
FOR /f %%m IN (%address%) DO ECHO %%m > NUL
IF NOT %%m==%m1% SET skipcount=%skipcount%+1 GOTO D 
GOTO C

This might work but I think it is full of mistakes for example syntax errors^^ So I am just trying to get a few hints to what is wrong:)

Upvotes: 1

Views: 219

Answers (2)

dbenham
dbenham

Reputation: 130819

You can use my JREPL.BAT regular expression text processing utility to create a tail command. JREPL.BAT is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward.

The following command will show the last line in chat.txt

call jrepl "^.*" "" /match /inc -1 /f chat.txt

But there is a much better way to develop a batch chat program (assuming that is a worthwhile goal)

You can have a batch process in a loop, with input redirected outside the loop, and the loop will read and write newly added lines as they appear. You could use SET /P and ECHO, but it is simpler to use a single FINDSTR. This works because FINDSTR does not reset the file pointer when called, as explained at http://www.dostips.com/forum/viewtopic.php?p=9720#p9720.

You should use some command to suspend processing briefly within the display loop to prevent the loop from consuming 100% of a CPU core. You could use TIMEOUT, or the PING hack, but they introduce a ~1 second delay. I chose to use PATHPING to introduce a ~0.2 second delay.

Also, you must worry about preventing collisions if two processes write to the same text file simultaneously. This can be solved by using lock files, as explained at How do you have shared log files under Windows?.

Below is the beginning of a rudimentary batch chat program. It works by having two or more users each navigate to the same shared directory, and then run chat.bat sessionName, where sessionName is an agreed upon name for the shared chat file. Each user will get the shared chat dialog displayed in their master console window, and a new console window will open where they can write their contributions to the conversation. Enter :quit to exit the chat program.

@echo off
setlocal disableDelayedExpansion
if "%~1" equ ":input" goto :startInput
if "%~1" equ ":display" goto :display
set "base=%~1"
set "dialog=%base%.chat"
set "quitfile=%base%_%username%.chat.quit"
start "" "%~f0" :input
del "%quitfile%" 2>nul
cmd /c "%~f0" :display
del "%quitfile%" 2>nul
exit /b


:display
title Chat Dialog
set "quit="
if not exist "%dialog%" (call ) >>"%dialog%"

<"%dialog%" (  for /l %%N in () do (
  if exist "%quitfile%" set "quit=1"
  findstr "^"
  if defined quit exit
  pathping -p 150 -q 2 localhost >nul
))

:startInput
setlocal enableDelayedExpansion
title Chat Input
call :write ">>> %username% has joined the conversation"
:input
cls
set "text="
set /p "text=>"
if /i !text! equ :quit (
  call :write "<<< %username% has left the conversation"
  copy nul "!quitfile!"
  exit
)
call :write
goto :input


:write
if "%~1" neq "" (set "text=%~1") else (set "text=%username%: !text!")
2>nul (
  >>"!dialog!" (
    echo(!text!
    (call )
  ) || goto :write
)
exit /b

Still to be done:

  • Provide a mechanism to invite users to a chat.
  • Provide an option to clear chat contents at the beginning of a new chat session (in case an old sessionName is reused)
  • Provide a :list command to list the currently participating users. This would require creation of sessionNameUserId files that would remain locked as long as the user is still listening and/or participating. The display loop could receive a :list command via a file, the same way as I implemented :quit, and then it could attempt to open each sessionNameuserID file for writing. If it fails then the user is still active, and the name should be listed.
  • I'm sure there are other things that might be useful.

Upvotes: 1

npocmaka
npocmaka

Reputation: 57252

here's a pure batch utility (requires no external tools) that can shows a range of numbered lines

to show the last line use it like this:

call tailHead.bat -file=address.txt -end=1

Upvotes: 2

Related Questions