您好,我有一个每小时创建和更新的日志文件, 它运行很多文件,因此很快就会填满。
我想做的是每隔一段时间清除一次,只留下文件的最后 30 行。
我尝试这样做已经有一段时间了,我知道有“更多”命令可以打印第 n 行中的行。我想要的是使用该命令或类似的命令,但我希望它写入文件而不是打印它。
这是我到目前为止所得到的。
set LINES=0
for /f "delims==" %%I in (test2.txt) do (
set /a LINES=LINES+1
)
@echo
set /a LINES=LINES-30
more +%LINES% < test2.txt
使用一些简单的逻辑技巧:
for /f %%i in ('type test2.txt^|find /c /v ""') do set /a lines=%%i-30
if %lines% leq 0 goto :eof
more +%lines% test2.txt>test2.tmp
move /y test2.tmp test2.txt
(这也算空行;Paul 的方法忽略它们。更好的是,取决于您的需求)
可能有一个更简单的解决方案,但这是我立即想到的一个。
@echo off
rem creating env testing
(
for /l %%i in (1,1,50) do (
echo %%i. What I want to do is to purge every once in a while only leaving the last 30 lines of the file.
)
)>%TEMP%\_file.tmp
rem Script start here.
set lines=0
for /f "delims=" %%i in (%TEMP%\_file.tmp) do set /a lines+=1
if %lines% LEQ 30 echo nothing todo &exit /b 0
set /a lines=lines-30
set "_skip=skip=%lines%"
set count=0
for /f "%_skip% delims=" %%i in (%TEMP%\_file.tmp) do (
echo %%i
set /a count+=1
)
echo found %count% lines
exit /b 0
这里的技巧是计算行数并减去 30,然后你就得到了必须跳过的行数。
这就是满足您需求的方式。
@echo off
set lines=0
for /f "delims=" %%i in (test2.txt) do set /a lines+=1
if %lines% LEQ 30 echo nothing todo &exit /b 0
set /a lines=lines-30
set "_skip=skip=%lines%"
(for /f "%_skip% delims=" %%i in (test2.txt) do (
echo %%i
))>%TEMP%\_file.tmp
move /Y %TEMP%\_file.tmp test2.txt
exit /b 0
虽然@Stephan的答案可能是最好的方法,但我仍然想贡献一个答案,这依赖于问题的代码......
这是原始代码的更正版本:
@echo off
set LINES=0
setlocal EnableDelayedExpansion
for /F "delims=" %%I in (test2.txt) do (
set /A "LINES=!LINES!+1"
)
endlocal & set /A "LINES=%LINES%-30"
if %LINES% GEQ 0 more +%LINES% test2.txt
有两个问题:
LINES
中读取像set /A
这样的变量或多或少相当于%LINES%
,但是这里需要延迟扩展和显式!LINES!
扩展;=
选项中的 delims=
太多(您不想指定 =
作为分隔符);但是,使用
for /F
实现仍然存在两个问题:
for /F
不考虑空行,因此不计算在内;;
开头的行也会被忽略,因为默认的 eol=
选项;如果稍微调整一下set /A
的语法,就可以避免
延迟扩展,并且可以克服有关空行和以
;
开头的行的问题:
@echo off
set /A "LINES=0"
for /F "delims=" %%I in ('
findstr /N /R "^" "test2.txt"
') do (
set /A "LINES+=1"
)
set /A "LINES-=30"
if %LINES% GEQ 0 more +%LINES% "test2.txt"
这里有一个
tail.bat
,可以像传统的 tail
命令一样使用。不,仍然没有 -fqv
功能。
@SETLOCAL
@SET EXITCODE=0
@SET /A LINES=10
@IF "%1" EQU "" (
@ECHO. usage: %0 [-n] filename^(s^)
@ECHO.
@ECHO. example: %0 -3 thefile.txt
@SET EXITCODE=1
@GOTO :EOF
)
@SET LC=%1
@IF "%LC:~0,1%" EQU "-" (
@SET /A LINES=%LC:-=%
@SHIFT
)
@SET FILENAME=%~1
@IF NOT EXIST "%FILENAME%" (
@ECHO. The file "%FILENAME%" does not exist.
@SET EXITCODE=2
@GOTO TheEnd
)
@FOR /F %%i IN ('TYPE "%FILENAME%" ^| FIND /C /V ""') DO @SET /A NLINES=%%i-%LINES%
@IF %NLINES% LEQ 0 (
@TYPE "%FILENAME%
) ELSE (
@MORE +%NLINES% "%FILENAME%"
)
:TheEnd
@EXIT /B %EXITCODE%
如果您知道机器/操作系统有可用的 PowerShell,则:
@echo off
PowerShell.exe -Command "(Get-Content \".\test2.txt\" -Tail 30) | Set-Content \".\test2.txt\""
由此带来的性能影响可能会低得多,其他批处理方法依赖于读取和计算批处理区域中的行数 - 并不总是那么好主意。