Bak Itzik
Bak Itzik

Reputation: 486

How to change variable value within BATCH file by the file itself?

I was looking for a long time now for an answer to this, learned nice tricks from http://www.dostips.com/DtTutoPersistency.php and http://ss64.com/nt/for_cmd.html sites, but still - don't have a solution to the problem I've encountered in: I have a BATCH file where I test the existence of specific folder (SendTo folder). In case I couldn't find it by the script - I want the user to enter the path to that folder - and keep the result in the BATCH file.

My narrowed BATCH file ("Some file.bat") looks something like:

@echo off

REM SomeNonsense

:: Win7/Vista
IF EXIST %APPDATA%\Microsoft\Windows\SendTo\NUL (
 REM Do something
 GOTO :EOF
)

:: WinXP
IF EXIST %USERPROFILE%\SendTo\NUL (
 REM Do something
 GOTO :EOF
)

:: Else
SET SendPath=
SET /P SendP="Please enter the path to the SendTo Folder:> "
IF EXIST %TMP%\SendPath.txt DEL %TMP%\SendPath.txt
FOR /F "usebackq TOKENS=* DELIMS=" %%A in ("%~0") DO (
 ECHO %%A>>%TMP%\SendPath.txt
 REM Later I want to change the value of SendPath with SendP,
 REM And swap the file back to the original name
)

My problem right now is that the lines of the file actually being interpreted, when I want only to copy the text itself to a temp file (without using COPY, because I want to copy line by line in order to change SendPath value).

Another thing is that empty lines aren't copied.

Any solution?

Upvotes: 1

Views: 2257

Answers (2)

MC ND
MC ND

Reputation: 70923

As a proof of concept

@echo off
    setlocal enableextensions disabledelayedexpansion

    call :persist.read

    if not defined savedValue (
        set /p "savedValue=Value to save:" && ( call :persist.write savedValue ) || (
            echo Value not set, process will end
            exit /b 1
        )
    ) 

    echo Saved value = [%savedValue%]

    goto :eof

:persist.read
    for /f "tokens=1,* delims=:" %%a in ('
        findstr /l /b /c:":::persist:::" "%~f0"
    ') do set "%%~b"
    goto :eof

:persist.write varName
    if "%~1"=="" goto :eof
    for %%a in ("%temp%\%~nx0.%random%%random%%random%.tmp") do (
        findstr /l /v /b /c:":::persist::: %~1=" "%~f0" > "%%~fa"
        >"%~f0" (
            type "%%~fa"
            echo(
            setlocal enabledelayedexpansion
            echo(:::persist::: %~1=!%~1!
            endlocal
        )
        del /q "%%~fa"
    )
    goto :eof

The problem with a batch file that edits itself while running is that it keeps pointers to the character position in the file where the commands are being executed. You can only make changes in lines after the current executing one and this can also generate other problems. So, the safest (not the more elegant nor the fastest) generic approach could be to write the data as comments at the end of the file.

Upvotes: 1

Aacini
Aacini

Reputation: 67216

This do what you want:

@echo off

rem Your previous Win7/Vista, WinXP testings here...

:: Else
call :defineSendPath

if defined SendPath goto continue

SET /P "SendPath=Please enter the path to the SendTo Folder:> "
rem Store the SendPath given into this Batch file:
echo set "SendPath=%SendPath%" >> "%~F0"

:continue

rem Place the rest of the Batch file here...


goto :EOF

rem Be sure that the following line is the last one in this file

:defineSendPath

Upvotes: 1

Related Questions