listbatch-filevariable-assignment

How would i make, access, and modify a flexible list in batch


I have a batch file that checks if a previously compiled exe file exists. If not, it will recompile, otherwise it will check if any files have been modified since the creation of the exe file. If modified files are found, it will recompile. It then checks through the directory, keeping track of the names and timestamps for the file contents.

I am wondering how to do this, so that I don't have to manually list:

file[0]=
file[1]=
file[2]=
etc.

Now I already have a list in here that is able to be modified whenenever, and works, but its modified like:

set SOURCES=!SOURCES! "%%F"

and my timestamp list is like:

set LIST=!LIST! %FILE_TIMESTAMP_FORMAT%

I've already checked a lot of sources, and none of them are dynamic, or just dont work for me. Also does anyone know why the format wont be echoed.

@echo off
setlocal enabledelayedexpansion

cd /d "C:\Users\ealos\OneDrive\Desktop\C++ Project"

echo Current directory: %CD%

set SOURCES=
set FILES_CHANGED=false
set LIST=

rem Check if cppgame.exe exists and get its timestamp
if exist cppgame.exe (
    for %%F in (cppgame.exe) do (
        set EXE_TIMESTAMP=%%~tF
    )
    echo cppgame.exe last modified: !EXE_TIMESTAMP!
    rem Convert cppgame.exe timestamp to comparable format
    set EXE_TIMESTAMP_FORMAT=!EXE_TIMESTAMP:~6,4!!EXE_TIMESTAMP:~0,2!!EXE_TIMESTAMP:~3,2!!EXE_TIMESTAMP:~11,2!!EXE_TIMESTAMP:~14,2!
    echo EXE Timestamp Format: !EXE_TIMESTAMP_FORMAT!
) else (
    echo cppgame.exe does not exist or was just created.
    set FILES_CHANGED=true
)

rem Loop through all .cpp files and check if any are newer than cppgame.exe
for %%F in (*.cpp) do (
    echo -----------
    rem Add the .cpp file to the SOURCES variable for compilation
    set SOURCES=!SOURCES! "%%F"
    
    rem Get the timestamp of the current .cpp file
    set FILE_TIMESTAMP=%%~tF
    rem Convert .cpp file timestamp to comparable format
    set FILE_TIMESTAMP_FORMAT=!FILE_TIMESTAMP:~6,4!!FILE_TIMESTAMP:~0,2!!FILE_TIMESTAMP:~3,2!!FILE_TIMESTAMP:~11,2!!FILE_TIMESTAMP:~14,2!
    
    echo Checking: %%F (Modified: !FILE_TIMESTAMP!)
    echo File Timestamp Format: (!FILE_TIMESTAMP_FORMAT!)
    
    rem Add the formatted timestamp to the LIST for comparison
    set LIST=!LIST! "%FILE_TIMESTAMP_FORMAT%"
    echo list: %LIST%
)

rem Now compare each timestamp in LIST with cppgame.exe's timestamp
echo %LIST%
for /f "tokens=1, delims==" %%a in (%LIST%) do (
    echo Comparing: %%a with !EXE_TIMESTAMP_FORMAT!
    if %%a GTR %EXE_TIMESTAMP_FORMAT% (
        set FILES_CHANGED=true
        echo File has changed, setting FILES_CHANGED=true
    )
    echo EXE Timestamp Format: !EXE_TIMESTAMP_FORMAT!
    echo File Timestamp Format: %%a
)

rem If no files have changed, just run the existing executable
if "!FILES_CHANGED!"=="false" (
    echo No files changed, running existing executable...
    cppgame.exe
    pause
    exit /b
)

rem If no .cpp files are found, exit
if "%SOURCES%"=="" (
    echo No .cpp files found in the directory!
    pause
    exit /b
)

rem Compile all .cpp files into a single executable (cppgame.exe)
echo Compiling...
g++ %SOURCES% -o cppgame.exe

rem Check if compilation was successful
if %ERRORLEVEL% NEQ 0 (
    echo Compilation failed!
    pause
    exit /b
)

rem Run the compiled executable
echo Running cppgame...
cppgame.exe

rem Pause to keep the console open after execution
pause

Solution

  • I believe the following would suit your requirement:

    @ECHO OFF
    SETLOCAL ENABLEDELAYEDEXPANSION
    rem The following setting for the directory is a name
    rem that I use for testing and deliberately includes spaces to make sure
    rem that the process works using such names. These will need to be changed to suit your situation.
    
    SET "sourcedir=u:\your files"
    SET "logfilename=%sourcedir%\q79528112.txt"
    
    SET "filesrequired=*.cpp final.exe"
    SET "abort="
    
    CALL :existing
    IF DEFINED abort GOTO cleanup
    FC "%logfilename%" "%logfilename%.new" >NUL 2>nul
    IF ERRORLEVEL 1 (
     ECHO recompile game
     CALL :existing
     MOVE /y "%logfilename%.new" "%logfilename%" >NUL
    )
    
    ECHO run game
    
    :cleanup
    DEL "%logfilename%.new" 2>nul
    
    GOTO :EOF
    
    :: Set #?? to current datestamp of required files & record in %logfile%.new
    :existing
    :: remove variables starting #
    FOR  /F "delims==" %%e In ('set # 2^>Nul') DO SET "%%e="
    
    PUSHD "%sourcedir%"
    FOR %%e IN (%filesrequired%) DO (
     IF EXIST "%%e" (SET "#%%e=%%~te") ELSE SET "abort=y"&ECHO %%e NOT found
    )
    popd
    
    SET #>"%logfilename%.new"
    
    GOTO :eof
    
    

    The name of the logfile simply suits my testing setup.

    The routine existing sets #filename to the datestamp of each file found on the filesrequired list, sets abort to y if any are missing and writes the list of filenames/datestamps to logfile.new.

    Then check whether the new logfile is the same as the old. If not, or one of the files is missing then recompile, reset the #variables with the new versions and re-write the log file.

    Then run the game and clean up any unwanted files.