使用批处理仅保留文本文件中的最后 30 行

问题描述 投票:0回答:5

您好,我有一个每小时创建和更新的日志文件, 它运行很多文件,因此很快就会填满。

我想做的是每隔一段时间清除一次,只留下文件的最后 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
windows batch-file cmd
5个回答
3
投票

使用一些简单的逻辑技巧:

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 的方法忽略它们。更好的是,取决于您的需求)


1
投票

可能有一个更简单的解决方案,但这是我立即想到的一个。

@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

1
投票

虽然@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

有两个问题:

  1. LINES
    中读取像
    set /A
    这样的变量或多或少相当于
    %LINES%
    ,但是这里需要延迟扩展和显式
    !LINES!
    扩展;
  2. =
    选项中的
    delims=
    太多(您不想指定
    =
    作为分隔符);

但是,使用

for /F
实现仍然存在两个问题:

  1. for /F
    不考虑空行,因此不计算在内;
  2. ;
    开头的行也会被忽略,因为默认的
    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"

0
投票

这里有一个

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%

0
投票

如果您知道机器/操作系统有可用的 PowerShell,则:

@echo off    
PowerShell.exe -Command "(Get-Content \".\test2.txt\" -Tail 30) | Set-Content  \".\test2.txt\""

由此带来的性能影响可能会低得多,其他批处理方法依赖于读取和计算批处理区域中的行数 - 并不总是那么好主意。

© www.soinside.com 2019 - 2024. All rights reserved.