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

时间:2015-09-24 07:25:56

标签: windows batch-file cmd

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

我想做的是每隔一段时间清除一次,只留下文件的最后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

5 个答案:

答案 0 :(得分: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

(这也算空行; Pauls方法忽略它们。什么更好,取决于你的需要)

答案 1 :(得分: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

答案 2 :(得分:1)

虽然@Stephan's answer可能是最好的方法,但我仍然希望提供答案,这取决于问题的代码......

以下是原始代码的更正版本:

@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%,但您需要delayed expansion并明确!LINES!扩展;
  2. =选项中有delims=太多(您不希望将=指定为分隔符);
  3. 但是,使用for /F实施仍存在两个问题:

    1. for /F不考虑空行,因此不计算;
    2. 由于默认;选项,
    3. eol=开头的行也会被忽略;
    4. 更新

      如果您稍微调整set /A的语法,则可以避免delayed expansion,并且可以克服与;开头的空行和行相关的问题:

      @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"
      

答案 3 :(得分: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%

答案 4 :(得分:0)

如果你知道机器/操作系统有PowerShell,那么:

@echo off    
PowerShell.exe -Command "Get-Content \".\test2.txt\" -Tail 30" > test2.txt

由此产生的性能可能会低得多,其他批次方法依赖于读取和计算批量生产线 - 不总是那么好。