views:

838

answers:

4

I want to write a bat script to check a text file (log). If the log is over 10M, I want to delete some portion of the file, only keep the last 500 lines, and delete all the old content.

So there are two issues: how can I check the file every 1 minute, and how can I delete only a portion of the content?

+1  A: 

Hi there.

I can help with the first point by suggesting that you create a scheduled task, in Windows, for the batch file to run every minute.

Regards the second point, about deleting a portion of the file, there is no way in batch file you can do that. You would have to use VBScript, or build a .NET console app to do the job. You could download Visual Basic/C# express and write that console app.

EDIT: My mistake, it doesn't look a scheduled task can run every minute. In that case you're better off writing a windows service to run the task every minute. I don't know how comfortable you'd be with doing that?

Cheers. Jas.

Jason Evans
why is there no way to delete a portion of a file from a batch script?
ax
i want to know as well
shrimpy
As far as I can tell, the Windows batch file commands does not contain anything that can manipulate the contents of a file. Only PowerShell or writing your own utility app using a programming language will do this.
Jason Evans
Oh and VBscript, that can alter the contents of files too.
Jason Evans
Windows Scripting Host (WSH) and either VBScript or JScript can do this. Even better (IMO) would be PowerShell.
Richard
Jason: Take a look at `for /f`. Of course you can work with the contents of a file. Editing in-place isn't possible, though but you never do (can't) that with text files anyway.
Joey
+1  A: 

You can use tail.exe, which is part of the Windows Server 2003 Resource Kit:

Tail is a command-line tool that displays a user-specified number of the last lines of a text file, such as a log file, in a console window.

For the repeated execution part, as others mentioned, you can use Windows Task Scheduler, which allows you to run the task at a frequency up to every 5 minutes.

As for the requirement to run every minute, that seems unnecessarily high to me. Does your log file get 10 MB of text every minute? That means it would grow to 15 GB in a day! Even checking it every 5 minutes seems high.

JRL
+1 for the not running every minute
ax
+1  A: 

You may want to look into a PowerShell based solution.

This script isn't exactly what you want, but it's close

$fsw = New-Object System.IO.FileSystemWatcher 
$fsw.Path = $env:TEMP
$fsw.Filter = "log.txt"
while ($true)
{
    Write-Host "Waiting"
    if ($fsw.WaitForChanged("Changed",1000).ChangeType -eq "Changed")
    {
     $len = Get-ItemProperty -Path $env:TEMP\log.txt -Name Length
     if ($len.Length -gt 10GB)
     {
      Write-Host "Removing"
      Remove-Item $env:TEMP\log.txt
     }
    }
}
Scott Weinstein
+1  A: 

This batch script will truncate a file if it is larger than 10 MB. It will write the last 500 lines to a temp file and then overwrite the original file with the temp file. You can adjust the file size and line count by changing the appropriate variable values.

You can use this script in a scheduled task as descibed by Jason Evans. Actually it is possible to launch the task every minute. Easiest way to achieve this is to create a task with any schedule configuration and afterwards edit it. Then you have extended properties for the scheduling intervals, like every minute.

Here is the script:

@ECHO OFF

REM REMAINING_LINES holds the number of lines to keep 
SET REMAINING_LINES=500

REM define file size limit to be 10 MB
SET FILE_SIZE_LIMIT=10737418240

REM check if file exists
IF NOT EXIST "%1" GOTO END

REM check file size by parsing the output of DIR command
FOR /F "tokens=3" %%A IN ('dir /-c /n "%1" ^| more +5') DO (
    IF /I %%A GTR %FILE_SIZE_LIMIT% GOTO TRUNCATE
    GOTO END
)

:TRUNCATE

REM COUNT holds the number of lines in the file
SET COUNT=0

REM count lines by incrementing count by 1 for each line in input file
FOR /F %%l in ('type "%1"') DO SET /A COUNT+=1

REM calculate the line offset
SET /A LINE_OFFSET=%COUNT%-%REMAINING_LINES%

REM check we have at least two lines remaining
IF /I %LINE_OFFSET% LEQ 1 GOTO END

REM write remaining lines to temp file
MORE +%LINE_OFFSET% "%1" > "%1.tmp"

REM overwrite input file with temp file 
MOVE /Y "%1.tmp" "%1"

ECHO %1 truncated.

:END
Frank Bollack