Batch delayed expansion not working - windows

Ok, I'm getting crazy and I don't know what else to do, I've tried several things and nothing is working.
Look at this sample code (test.cmd):
setlocal enabledelayedexpansion enableextensions
set VAR=before
if "%VAR%" == "before" (
set VAR=after;
if "%VAR%" == "after" #echo If you see this, it worked
)
This is the generated output:
D:\>ver
Microsoft Windows [Version 6.1.7600]
D:\>test.cmd
D:\>setlocal enabledelayedexpansion enableextensions
D:\>set VAR=before
D:\>if "before" == "before" (
set VAR=after;
if "before" == "after"
)
D:\>
Am I doing something wrong?
This is just a test, the code I need uses variables too and needs delayed expansion, but it this simple test doesn't work the other wont work either (I've tried, I ended up with a simple example to test if it worked).
EDIT: New code and output:
test.cmd:
#echo off
setlocal enabledelayedexpansion enableextensions
set VAR=before
if "%VAR%" == "before" (
set VAR=after;
if "!VAR!" == "after" (
echo It worked.
) else (
echo It didn't work.
)
)
Output:
D:\>test.cmd
It didn't work.
D:\>

You have to use !var! for delayed expansion. %var% is always expanded on parse stage.
I.e., change your code to
setlocal enabledelayedexpansion enableextensions
set VAR=before
if "%VAR%" == "before" (
set VAR=after
if "!VAR!" == "after" #echo If you see this, it worked
)

At the beginning of the cmd prompt, you must type “CMD /V” OR “CMD /V:ON”
After this testing code should work
SETLOCAL EnableDelayedExpansion
Set "_var=first"
Set "_var=second" & Echo %_var% !_var!
You should be able to see output “first second”

dont use == , in batch you must use EQU
For Example write:
if %bla% EQU %blub% echo same

I found your problem.
set VAR=after;
delete ; from the code above

Related

Windows batch if not equal do not execute if clause

I have a .bat file to execute in a windows server 2012 R2 machine. Problem is that I need to add an "if not equals" but when I try to execute it the code does not work.
I know that problem is in the if because I tried without the if and it works.
setlocal enabledelayedexpansion
set anno=%date:~6,4%
set mese=%date:~3,2%
set giorno=%date:~0,2%
set ore=%time:~0,2%
set minuti=%time:~3,2%
set secondi=%time:~6,2%
e:
mkdir "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
move \\gbjob09\Info-Bit\Sql_Ges\PRESENZE\2019\*.old "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
cd "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
for /f %%a in ('dir /b *.old') do (
set originalname=%%a
set timbrnumber=!originalname:~4,4!
if NOT %timbrnumber% == "0584" (
if NOT %timbrnumber% == "0585" (
set shortname=9!originalname:~4,4!
echo !shortname!
for /f "tokens=*" %%b in (%%a) do (
echo %%b!shortname!>> "Presenze.txt"
)
)
)
)
copy "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%\Presenze.txt" "E:\Presenze\presenze.txt"
exit
Like you can see the problem is only this really small part:
if NOT %timbrnumber% == "0584" (
I already tried to remove the double if but it still does not work.
I know that the old code (this one) works:
setlocal enabledelayedexpansion
set anno=%date:~6,4%
set mese=%date:~3,2%
set giorno=%date:~0,2%
set ore=%time:~0,2%
set minuti=%time:~3,2%
set secondi=%time:~6,2%
e:
mkdir "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
move \\gbjob09\Info-Bit\Sql_Ges\PRESENZE\2019\*.old "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
cd "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%"
for /f %%a in ('dir /b *.old') do (
set originalname=%%a
set shortname=9!originalname:~4,4!
echo !shortname!
for /f "tokens=*" %%b in (%%a) do (
echo %%b!shortname!>> "Presenze.txt"
)
)
copy "E:\Presenze\%anno%%mese%%giorno%%ore%%minuti%%secondi%\Presenze.txt" "E:\Presenze\presenze.txt"
exit
I only added a variable:
set timbrnumber=!originalname:~4,4!
that should work (it shouold get 4 characters after exclude 4 characters of the originalname variable) like shortname print 9 and 4 characters after exclude 4 characters of the originalname variable, but I'm not really sure because I don't really know windows batch (this is the first time that I use it and the original code was not mine).
After that I only need to check if timbrnumber is not "0584" and it's not "0585" but everything I tried was a fail.
In short, as your variable is being set and used inside a code block and double quoting is required both sides of the ==, this section should fix your issue:
if NOT "1!timbrnumber! == "10584" (
if NOT "!1timbrnumber!" == "10585" (
which can be better written as:
if 1!timbrnumber! neq 10584 (
if 1!timbrnumber! neq 10585 (
Another observation, your time:
set ore=%time:~0,2%
set minuti=%time:~3,2%
set secondi=%time:~6,2%
can be better created as:
set mytime=%time::=%
echo %mytime:0,6%

windows batch script replace substring in a if condition

trying to replace 11/22/2016 to 11222016. for this I have tried the following and is working as expected.
set string=dd/mm/yyyy.
set find=/
set replace=
call set string=%%string:!find!=!replace!%%
echo %string%
output is ddmmyyyy
but when I tried this in the if condition this is not working as expected.
setlocal enabledelayedexpansion
set isDateFound=false
set string=dd/mm/yyyy.
if "%isDateFound%" == "false" (
echo %isDateFound%
set find=/
set replace=
call set string=%%string:!find!=!replace!%%
echo %string%
)
output dd/mm/yyyy
looks like the delayedexpressions is playing some role here. but I am not able to overcome this. How replace substring in side the if condition.
Here is a better way to do that :
#echo off
FOR /F "tokens=1-3" %%a IN ('WMIC Path Win32_LocalTime Get Day^,Month^,Year ^| findstr [0-9]') DO (
set "$Day=0%%a"
set "$Month=0%%b"
set "$Year=%%c"
)
echo %$Year%%$Month:~-2%%$Day:~-2%
The leading 0 before before Month and Day is automatically added.
You are using delayed expansion in your set call so in this case you need to access the value via !string! not %string%, so:
setlocal enabledelayedexpansion
set isDateFound=false
set string=dd/mm/yyyy.
if "%isDateFound%" == "false" (
echo %isDateFound%
set find=/
set replace=
call set string=%%string:!find!=!replace!%%
echo !string!
)
note echo !string! instead of echo %string%

Print variable in batch file

I am trying to print a variable in parenthesised code which is assigned a value using other variable in batch file.
Here is my code
#echo off
SETLOCAL enableDelayedExpansion
CALL initialize
CALL fun
:fun (
#echo off
Setlocal EnableDelayedExpansion
Set "SOMEVAR=!OTHERVAR!"
ECHO ..%SOMEVAR%
EXIT /B 0
)
:initialize (
set SOMEVAR=somevalue
EXIT /B 0
)
The output is just
..
How do i fix it so that i can assign value to somevar?
Edit1: If i now try to print in following way it does its job
ECHO ..!SOMEVAR!
But my script uses lot of %SOMEVAR%. Does that mean i need to change them all?
Note: Othervar is initialzed in other function and it does show proper value if it is echoed.
Since the code portion containing echo %SOMEVAR% is in between parenthesis, the variable is expanded before being set (consult this post for a good explanation).
There are the following options to avoid that:
to expand it like !SOMEVAR! (delayed expansion), or
to avoid the parenthesis:
#echo off
SETLOCAL EnableDelayedExpansion
CALL initialize
CALL fun
exit /B
:fun
Setlocal EnableDelayedExpansion
Set "SOMEVAR=!OTHERVAR!"
ECHO ..%SOMEVAR%
EXIT /B 0
:initialize
set SOMEVAR=somevalue
EXIT /B 0
Note the additional exit /B in the above code snippet after the call statements, which prevents from falling into the code below unintentionally.
Does this work any closer to your expectations? Note that SOMEVAR will not be returned to your shell environment unless an ENDLOCAL block is used.
C:>set OTHERVAR=0123456789
C:>type g2.bat
#echo off
SETLOCAL enableDelayedExpansion
CALL:initialize
CALL:fun
EXIT /B 0
:fun (
rem #echo off
Setlocal EnableDelayedExpansion
Set "SOMEVAR=!OTHERVAR!"
ECHO ..%SOMEVAR%
GOTO :EOF
)
:initialize (
set SOMEVAR=somevalue
GOTO :EOF
)
C:>g2.bat
..0123456789

The syntax of the command is incorrect. at endlocal & set [batch]

I have a function which returns value by reference in batch.
:errorCheck
setlocal
set "test_command=%~1"
set "err_code=%~2"
FOR /F "delims=" %%a IN ('%test_command% 2^>^&1 1^>NUL') DO (
set err_msg="%%~a"
)
if [%err_msg%] neq [] (
if not x%err_msg:%err_code%=%==x%err_msg% (
set "error=true"
)
)
if [%err_msg%]==[] (
set "error=false"
)
endlocal & set "%3=%error%"
exit /b
The function executes correctly and the return value is also correct but at line endlocal & set "%3=%error%" while executing set "%3=%error%" part it gives me error :
The syntax of the command is incorrect.
i am unable to comprehend why is it happening though the return value is correct.
The problem is not in the return value, but in the substring operation. Your syntax is not allowed. The expression is not evaluated as you think. The start and end of variables are
%err_msg:%err_code%=%
^........^ ^.^
var1 var2
To use a variable in a substring operation in another variable you will need to use delayed expansion. Try with
:errorCheck
setlocal enableextensions disabledelayedexpansion
set "test_command=%~1"
set "err_code=%~2"
set "error=false"
set "err_msg="
FOR /F "delims=" %%a IN ('
%test_command% 2^>^&1 1^>NUL
') DO set "err_msg=%%~a"
if defined err_msg (
setlocal enabledelayedexpansion
if not "!err_msg:%err_code%=!"=="%err_msg%" (
endlocal
set "error=true"
) else ( endlocal )
)
endlocal & set "%3=%error%"
exit /b
Now the variables seen by the parser are
!err_msg:%err_code%=!
^........^
^...................^
But as not all characters are allowed in a substrig operation, depending on the contents of err_code it is possible that it will also fail.
If it can be the case, you can change the substring operation into a piped command searching for the required error code
:errorCheck testCommand errorCode returnVariable
setlocal enableextensions disabledelayedexpansion
( %~1 2>&1 1>nul | find "%~2" > nul ) && ( set "error=true" ) || ( set "error=false" )
endlocal & set "%~3=%error%"
exit /b
That is:
execute the command (%~1) with, as in the original code, the stdout redirected to null and stderr redirected to stdout, so we read the error stream.
The output of the command is filtered with find, searching the error code. If it is found, find will not raise error level, if it is not found, errorlevel will be raised.
Using conditional execution, the error variable is set. If the previous command does not raise errorlevel, the code after the && is executed. If the command raised errorlevel, the code after the || is executed.
Environment space is restored and the return variable asigned

If syntax in windows batch

I'm trying to make this work in a windows batch file:
if not exist "%~n1.ext" (
set /P z="PROMPT (y,n)?"
if /i "%z%" == "y" (
echo if is working
)
)
But no matter what the input is, it never goes into the echo part. Is there something wrong in the syntax?
When you use a variable inside a block (between (and ), you need to enable delayed expansion:
setlocal enabledelayedexpansion
set var=hello
if "a"=="a" (
set var=world
echo %var% !var!
)
Stephan is correct, you need to use enabledlayedexpansion when using a nested variable. Here's your code with that syntax (replacing % with ! when using such variables):
setlocal enabledelayedexpansion
if not exist "%~n1.ext" (
set /P z="PROMPT (y,n)?"
if /i "!z!" == "y" (
echo if is working
)
)

Resources