mst3kzz
mst3kzz

Reputation: 13

Batch file to output lines after string match, filename

I have a directory of thousands of text files that begin with tape* (they're output files from an old Fortran program) and I need to extract 4 lines from each file as well as the filename that they were extracted from. The 4 lines begin 4 lines down from a predictable string, but we can use "Header" for this example:

tape1:

First line
...
Header
Trash1
Trash2
Trash3
Data1
Data2
Data3 
Data4 
...

I don't care about anything before or after those 4 data lines, but I also want the filename (i.e. "tape1") output after each Data line, like so:

Data1 tape1
Data2 tape1 
Data3 tape1 
Data4 tape1
Data5 tape2
Data6 tape2 
...

Any thoughts on an easy Windows batch file to do this on all tape* files in a directory?

Upvotes: 1

Views: 2056

Answers (3)

Aacini
Aacini

Reputation: 67326

@echo off
setlocal EnableDelayedExpansion

for /F "tokens=1,2 delims=:" %%a in ('findstr /N "Header" tape*') do (
   (for /L %%i in (-2,1,%%b) do set /P "="
    for /L %%i in (1,1,4) do set /P "line=" & echo !line! %%a
   ) < "%%a"
)

Upvotes: 3

thx1138v2
thx1138v2

Reputation: 566

@echo off
cls
rem get a list of file names sorted alphabetically by name
dir /b tape* /ON>.\Files.txt

rem delete any existing output from any previous run
if exist .\FoundData.txt del .\FoundData.txt

SET DataFileName=
SET LineData=
SET FoundData=

SETLOCAL ENABLEDELAYEDEXPANSION
FOR /F %%A IN (.\Files.txt) DO (
    SET DataFileName=%%A

    FOR /F "tokens=1,2* " %%B IN (!DataFileName!) DO (
        rem use the following line to get just the first word on the line 
        rem SET LineData=%%B

        rem use the following line to get the entire line
        SET LineData=%%B %%C %%D

        rem determine if the line contains "DATA" (case insensitive) and if so capture it
        if "%FoundData%"=="" ( ECHO !LineData!|FIND /I "DATA">Nul && (SET FoundData=!LineData! ) || (SET FoundData=) )

        rem if the line contained the data we want output it to the output file
        IF NOT "!FoundData!"=="" ( 
            (ECHO !FoundData! !DataFileName!>>.\FoundData.txt) 
        )
    )
    SET LineData=
    SET FoundData=
)
set DataFileName=
)
ENDLOCAL
if not exist .\FoundData.txt echo No data found>.\FoundData.txt
start notepad .\FoundData.txt  

Upvotes: 0

aschipfl
aschipfl

Reputation: 34989

You could try the following:

@echo off
for %%F in (".\tape*.txt") do (
    for /F "delims=:" %%N in ('findstr /N /X /C:"Header" "%%~F"') do (
        call :SUB "%%~F" %%N
    )
)
exit /B

:SUB
set /A "SKIP=%~2+3"
for /F "skip=%SKIP% usebackq delims=" %%L in ("%~1") do (
    echo(%%L %~n1
)
exit /B

Here is an alternative approach:

@echo off
for %%F in (".\tape*.txt") do (
    for /F %%C in ('^< "%%~F" find /C /V ""') do (
        set /A "POS=0" & set "NAME=%%~nF"
        < "%%~F" (
            setlocal EnableDelayedExpansion
            for /L %%I in (1,1,%%C) do (
                set "LINE=" & set /P LINE=""
                if "!LINE!"=="Header" (
                    set /A "POS=%%I+3"
                )
                if !POS! GTR 0 if %%I GTR !POS! (
                    echo(!LINE! !NAME!
                )
            )
            endlocal
        )
    )
)

Upvotes: 0

Related Questions