stringwindowsif-statementbatch-filefindstr

How to modify lines that hold a given string with new information and save it as a text file


I am working on modifying our batch files where we call @make functions inside. We want to add a script inside the batch file that checks an external header file, finds the line with date information(APP_VERSION_DATE) and updates the information there with new date information(I figured out how to fetch windows date information with batch, this is not an issue)

I know what steps to follow but batch syntax feels completely counter intuitive to me and I am stuck.

These are the steps I would like to follow:

1- Go through the app_version.h file line by line(for /f)

2- Find the lines with string APP_VERSION_DATE(if findstr...)

3- delete everything except APP_VERSION_DATE

4- CONCAT date information to APP_VERSION_DATE like APP_VERSION_DATE "23-05-2022"

5- Keep echoing every other line

6- Pipeline the information a new header file.

7- Delete header file

8- Rename the new header line as the old one.

set strToFind="app_version_date"
set result="Not Found"
for /f "tokens=2 delims=[]" %%A in ('findstr %strToFind% %filename%') do (
      set result=%%A
      if defined result (
           if  %result%==this is something 
           echo hurra this is it
      ) ELSE echo    
)

this is where I am at right now and I am obviously still too far off to do something I want to do.

I am able to make a program that can find a given string in a file and change it but in this case I want to find the line that has the string I am searching for, delete the rest and modify it. I want to find the line where the string is and modify it, not the string itself. This is simply because date information as shown below;

#define APP_VERSION_DATE [2022-05-16 12:13]

won't be static and ever changing with each compile attempt.

I have something like this but this is too far from what I want to do.

Any help would be great! Thanks in advance


Solution

  • Replace date/time in header file app_version.h

    There could be used the following commented batch file for this task:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    set "HeaderFile=app_version.h"
    if not exist "%HeaderFile%" exit /B 20
    
    rem Get current local date/time in format [yyyy-MM-dd HH:mm].
    for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do set "AppVersionDate=[%%G-%%H-%%I %%J:%%K]" & goto UpdateHeaderFile
    
    rem Let FINDSTR output all lines of the header file with a line number and
    rem a colon at the beginning for processing really all lines including the
    rem empty lines in the header file and output all lines without the line
    rem number and the colon with exception of the line containing the string
    rem #define APP_VERSION_DATE which is ignored and instead is output a line
    rem defined here with the local date/time determined before. All lines output
    rem by the loop are written into a newly created temporary header file.
    
    :UpdateHeaderFile
    (for /F delims^=^ eol^= %%I in ('%SystemRoot%\System32\findstr.exe /N "^" "%HeaderFile%" 2^>nul') do (
        set "Line=%%I"
        setlocal EnableDelayedExpansion
        if "!Line:#define APP_VERSION_DATE=!" == "!Line!" (
            echo(!Line:*:=!
        ) else (
            echo #define APP_VERSION_DATE %AppVersionDate%
        )
        endlocal
    ))>"%HeaderFile%.tmp"
    
    rem Replace the original header file with the temporary header file.
    if exist "%HeaderFile%.tmp" move /Y "%HeaderFile%.tmp" "%HeaderFile%" >nul
    
    rem Delete the temporary header file if the command line above failed
    rem because of the original header file is read-only or write-protected
    rem or currently opened by an application with shared access denied.
    if exist "%HeaderFile%.tmp" del "%HeaderFile%.tmp"
    
    endlocal
    

    The environment variable HeaderFile can be defined with an absolute path or a relative path.

    Please read the chapter Usage of ROBOCOPY to get current date/time in my answer on Time is set incorrectly after midnight for an explanation of the first for /F command line.

    Please read next my answer on How to read and print contents of text file line by line? It describes in full details the second for /F loop with the small modification of an additional IF condition to replace the line containing the string #define APP_VERSION_DATE with an current date/time.

    To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.

    See also single line with multiple commands using Windows batch file for an explanation of the unconditional command operator &.


    Create header file current_date_time.h with date/time

    The task could be done much easier if the file app_version.h contains anywhere the line:

    #include "current_date_time.h"
    

    The batch file could be in this case just:

    @echo off
    setlocal EnableExtensions DisableDelayedExpansion
    for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do echo #define APP_VERSION_DATE [%%G-%%H-%%I %%J:%%K]>"current_date_time.h"& goto EndBatch
    :EndBatch
    endlocal
    

    This batch file always creates new the file current_date_time.h with just the single line:

    #define APP_VERSION_DATE [2022-05-23 18:48]
    

    And this single preprocessor macro definition line is included on compilation into app_version.h.


    Define preprocessor macro APP_VERSION_DATE with current date/time

    Every C/C++ compiler has an option to define a preprocessor macro on the command line and the option can be used multiple times on the command line to define multiple preprocessor macros.

    For example see:

    So it is possible to define an environment variable with the current date/time in the wanted format with the single command line below and reference this environment variable value on running the C/C++ compiler with the appropriate option.

     @set "AppVersionDate=" & for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do @if not defined AppVersionDate set "AppVersionDate=[%%G-%%H-%%I %%J:%%K]"
    

    GNU gcc/g++ would be run later with -D "APP_VERSION_DATE=%AppVersionDate%" and Microsoft C/C++ compiler with /D "APP_VERSION_DATE=%AppVersionDate%" as one of the options on compilation of the C/C++ source code files.

    There are also the predefined macros __DATE__ and __TIME__:

    Search also for information about the environment variable SOURCE_DATE_EPOCH which gives control over the timestamp added by the C/C++ compiler itself to the produced binaries.