windows 只保留文本文件中的最后30行

ubbxdtey  于 2023-10-22  发布在  Windows
关注(0)|答案(5)|浏览(198)

你好,我有一个日志文件,我创建和更新每小时,它运行了很多文件,因此它填补了非常快。
我想做的是每隔一段时间清除一次,只留下文件的最后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
mwngjboj

mwngjboj1#

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

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

(this还计数空行;保罗的方法忽略了他们。什么更好,取决于您的需求)

kadbb459

kadbb4592#

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

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

monwx1rj3#

虽然@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.阅读像set /A中的LINES这样的变量或多或少等同于%LINES%,但是这里需要delayed expansion和显式的!LINES!扩展;
1.在delims=选项中有一个=太多(您不希望将=指定为x1);
但是,使用for /F实现仍然存在两个问题:

  1. for /F不考虑空行,因此不计入;
    1.以;开头的行也被忽略,因为默认的eol=选项;

更新

如果稍微修改一下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"
cgfeq70w

cgfeq70w4#

下面是一个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%
gv8xihay

gv8xihay5#

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

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

这样做对性能的影响可能会低得多,其他批处理方法依赖于阅读和计数批处理区域中的行-并不总是一个好主意。

相关问题