Search code examples
batch-filefor-loopskip

How to use for /f skip to delete lines from beginning of text file


Still suffering from expansion dysfunction, I fear. I'm trying to strip lines GTR than 100 from the beginning of log files. The following looks to me like it should work, but as shown, the for /f "skip" near end isn't working. Can someone kindly explain what's wrong here? Thank you!

@echo off
SETLOCAL EnableDelayedExpansion

Set "logfile=abc.log"

rem ~ Get line count and exit if not greater 100
  For /f %%G in ('Type "!logfile!"^|Find "" /v /c') Do SET /a linecount=%%G
  If not %linecount% GTR 100 exit /b

rem ~ get number lines to skip
  set /a skiplines=!linecount! -100
  echo. &echo logfile=%logfile%, linecount=%linecount%, skiplines=%skiplines%
  :: Above displays: logfile=abc.log, linecount=243, skiplines=143

:: HERE'S THE PROBLEM:

rem ~ skip the first %skiplines% in file and write remaining to temp
  for /f "skip=!skiplines! delims=*" %%H in ("!logfile!") do echo %%H >>newfile.tmp

:: Above give error: "!skiplines! delims=*" was unexpected at this time."

  for /f "skip=%skiplines% delims=*" %%H in ("!logfile!") do echo %%H >>newfile.tmp

:: (as expected, above writes 0 to newfile.tmp)

One Solution - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

I'm editing to show this one-line solution prominently along with accepted answer. The code required usebackq, as included in @Magoo answer. This works:

for /f "usebackqskip=%skiplines% delims=*" %%H in ("!logfile!") do echo %%H>>newfile.tmp

Solution

  • It's a matter of when !var! and %var% are evaluated in the process. %var% is evaluated (substituted) first but !var! is only evaluated after the loop 's conditions are established, hence !var! is not expected in that position.

    The solution is to only use !var! as intended, (within loops) where the value is determined at run-time, not parse-time. Use %var% to access the parse-time value. Don't treat !var! and %var% as equivalent outside of loops. For come commands they effectively are, but not all.

    BTW - watch what happens when linecount is exacly 100. SKIP does not like 0. I'd change the GTR to GEQ if I were you...


    Here's a routine that should demonstrate what's happening. It uses my work area - you'd need to alter it for your system, no doubt.

    @ECHO OFF
    SETLOCAL
    :: Just setting up data
    SET "sourcedir=U:\sourcedir"
    Set "logfile=abc.log"
    
    PUSHD "%sourcedir%"
    (
     FOR /l %%a iN (1,1,99) DO ECHO line %%a
    )>"%logfile%"
    
    CALL :process
    >>"%logfile%" ECHO line 100
    CALL :process
    >>"%logfile%" ECHO line 101
    CALL :process
    >>"%logfile%" ECHO line 102
    CALL :process
    
    popd
    GOTO :eof
    
    :process
    
    For /f %%G in ('type "%sourcedir%\%logfile%"^|Find "" /v /c') Do SET /a linecount=%%G
    
    ECHO %linecount% lines IN log file
    
    IF %linecount% leq 100 EXIT /b
    
    ECHO MORE than 100 lines!!
    
    SET /a skiplines=linecount - 100
    SET /a skiplines2=%linecount% - 100
    ECHO ------- observe response from this instruction
    SET /a skiplines3=!linecount! - 100
    ECHO ------- this is because of the sequence-of-evaluation-and-substitution
    
    SET skipline
    
    :: delete the output file
    DEL newfile.tmp >NUL 2>NUL
    
    FOR /f "usebackqskip=%skiplines% delims=*" %%H IN ("%sourcedir%\%logfile%") DO ECHO %%H >>newfile.tmp
    ECHO =====================
    ECHO after skipping %skiplines% of %logfile% result is
    TYPE newfile.tmp
    ECHO =====================
    EXIT /b
    

    The result should be

    99 lines IN log file
    100 lines IN log file
    101 lines IN log file
    MORE than 100 lines!!
    ------- observe response from this instruction
    Missing operator. 
    ------- this is because of the sequence-of-evaluation-and-substitution
    skiplines=1
    skiplines2=1
    skiplines3=0
    =====================
    after skipping 1 of abc.log result is
    line 2 
    line 3 
    ...
    line 100 
    line 101 
    =====================
    102 lines IN log file
    MORE than 100 lines!!
    ------- observe response from this instruction
    Missing operator.
    ------- this is because of the sequence-of-evaluation-and-substitution
    skiplines=2
    skiplines2=2
    skiplines3=0
    =====================
    after skipping 2 of abc.log result is
    line 3 
    line 4 
    ...
    line 101 
    line 102 
    =====================