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
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.
del /?
echo /?
endlocal /?
exit /?
findstr /?
goto /?
if /?
move /?
rem /?
set /?
setlocal /?
See also single line with multiple commands using Windows batch file for an explanation of the unconditional command operator &
.
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
.
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:
-D
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.