Batch file - changing variable value in a for loop - batch-file

I have following code snippet
setlocal enableextensions enabledelayedexpansion
set b=123
for %%f in (.\input\*.mgc) do (
set "b=%%~nf"
echo %b%
)
I am expecting it to output file name with no extension but I always get "123". I concluded it has something with late expansion but not quite sure where the problem comes from. I have also tried with echo !b! but in that situation it outputs only "!b!"

Try replacing %b% with !b! as explained here:
The variable whose expansion should be delayed should be surrounded by exclamation marks instead of percent signs.
setlocal enableextensions enabledelayedexpansion
set b=123
for %%f in (.\input\*.mgc) do (
set "b=%%~nf"
echo !b!
)

I believe in hard evidence. I can't see you execute the code or if you are obfuscating the code at all so here is me executing your code. It works just like I said.
C:\BatchFiles\SO>type testing.bat
#echo off
setlocal enableextensions enabledelayedexpansion
set b=123
for %%f in (.\input\*.mgc) do (
echo %%~nf
set "b=%%~nf"
echo !b!
)
pause
C:\BatchFiles\SO>dir /b .\input\*.mgc
testfile.mgc
C:\BatchFiles\SO>testing.bat
testfile
testfile
Press any key to continue . . .
C:\BatchFiles\SO>

Related

batch file variable doesn't work inside if statement, even with delayed expansion?

I'm writing a batch file that will modify an input file but only if the filename contains -source.
This works:
#echo off
#setlocal ENABLEDELAYEDEXPANSION
set fn=%1
echo Checking %fn%...
set outfile=%fn:-source=%
if not x%fn:-source=%==x%fn% (
echo Output to %outfile%
)
but this does not:
#echo off
#setlocal ENABLEDELAYEDEXPANSION
set fn=%1
echo Checking %fn%...
if not x%fn:-source=%==x%fn% (
set outfile=%fn:-source=%
echo Output to %outfile%
)
In the second case, it simply outputs "Output to" with no file name. How can I fix this?
Here's your second script again, with my answer from my comment and some additional improvements with regard double quoting.
#Echo Off
If "%~1"=="" Exit/B
Set "fn=%~1"
Echo Checking %fn%...
SetLocal EnableDelayedExpansion
If Not "x%fn:-source=%"=="x%fn%" (
Set "outfile=%fn:-source=%"
Echo Output to !outfile!
)
As an additional note, if "x%fn:-source=%" does equal "x%fn%" there is no need to use the If, (making a substitution which doesn't alter the value is harmless).
#Echo Off
If "%~1"=="" Exit/B
Set "fn=%~1"
Echo Checking %fn%...
Set "outfile=%fn:-source=%"
Echo Output to %outfile%

ECHO is off error while executing batch file

Executing batch file gives ECHO is off.
The batch file code is present below:
#echo off
setlocal EnableDelayedExpansion
SET a = Hello
SET b = World
SET /A d = 50
SET c = %a% and %b% %d%
echo %c%
endlocal
pause
As MC ND wrote, you have to get rid of spaces before and behind the equality sign. It should be SET a=Hello and not SET a = Hello and so on. This code works as expected:
#echo off
setlocal EnableDelayedExpansion
SET a=Hello
SET b=World
SET /A d=50
SET c=%a% and %b% %d%
echo %c%
endlocal
pause
Further, the lines setlocal EnableDelayedExpansion and endlocal are useless in your code as you never use the delayed expansion (e.g. !a! instead of %a%). Your code is still correct as there is doesn't need delayed expansion.
If you have further questions, please post them as such. Don't expand this post on other questions.
Here are your two, altered codes:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "a=Hello"
SET "b=World"
SET/A "d=50"
SET "c=%a% and %b% %d%"
ECHO %c%
ENDLOCAL
PAUSE
Please check and try them, then read up on the individual commands to learn from your errors.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET/P "pathToJava= **Provide your Response: "
IF /I "%pathToJava%"=="Y" ECHO found
ENDLOCAL
PAUSE

Windows CMD Batch: FOR /R with DelayedExpansion

On my desktop, there is a folder named "test". Inside this folder is two files, "file1.txt" and "file2.txt".
Take a look at this simple batch script:
#ECHO OFF
SET test="C:\Users\Tyler\Desktop\test"
ECHO %test%
FOR /R %test% %%F IN (*) DO (
ECHO %%F
)
As you might expect, it outputs the following:
"C:\Users\Tyler\Desktop\test"
C:\Users\Tyler\Desktop\test\file1.txt
C:\Users\Tyler\Desktop\test\file2.txt
Now take a look at this variation:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET test="C:\Users\Tyler\Desktop\test"
ECHO !test!
FOR /R !test! %%F IN (*) DO (
ECHO %%F
)
ENDLOCAL
I would expect its output to be no different. However, here it is:
"C:\Users\Tyler\Desktop\test"
It appears that !test! gets expanded in the ECHO !test! line, but not in the FOR /R !test! line, becoming just !test!. Since that is, of course, not a valid path, the FOR /R loop never iterates.
Why is this? What am I missing?
Why FOR works different than ECHO is because the batch parser (cmd.exe) has special parsing rules for FOR, IF and REM.
Therefore delayed expansion doesn't work for the parameters here, only for the arguments inside the parenthesis.
Only percent expansion works for the parameters, as the parser executes the percent expansion phase just before it switches to the special FOR parser rules.
If you can't use percent expansion, as you are inside of a block you can move the code to an own function and call it.
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET test="C:\Users\Tyler\Desktop\test"
ECHO !test!
call :doMyLoop test
exit /b
:doMyLoop
set "arg=!%1!"
FOR /R %arg% %%F IN (*) DO (
ECHO %%F
)

Issue With Delayed Expansion In Batch Code

I am running into an issue where I have a complete directory listing of a computer (located in the text file shown below).
The issue appears in cases where the directory listing contains special characters such as "! or &". When that issue occurrs, the filename is parsed such that those special characters are omitted (thus causing issues with leveraging those variables to compute other sub-tasks). Below is a snapshot of the code. Please advise as to how I might proceed.
Note that within the text file might be paths such as:
C:\Windows!temp!\file.txt
C:\Windows\file.txt
This will parse as:
C:\Windows\temp\file.txt (without quotes)
C:\Windows\file.txt
code snip
for /f "delims=?" %%a in (dir.txt) do (
setlocal enabledelayedexpansion
set filepath=%%a
)
call :subproc1
)
goto :proc2
:subproc1
echo !filepath!
endlocal
goto :eof
:proc2
continue with script here
You are toggling delayed expansion on too early, and there is no need for the subroutine.
for /f "delims=?" %%a in (dir.txt) do (
set filepath=%%a
setlocal enabledelayedexpansion
echo !filepath!
endlocal
)
#echo off
setlocal enableDelayedExpansion
for /f "delims=?" %%a in (dir.txt) do (
setlocal disableDelayedExpansion
(echo(%%a)
endlocal
)
endlocal
goto :proc2
:proc2
echo -------end
the Jeb's trick...

Batch file to handle random % character in FOR LOOP

I am trying to pass file names as FOR loop parameters to a separate batch file. The problem is, if a file name contains special characters (especially %), the parameter doesnt go to the called script. EG -
The FIRST_SCRIPT.bat is as follows -
cd "C:\theFolder"
for /R %%a in (*.*) do call SECOND_SCRIPT "%%~a"
The SECOND_SCRIPT.bat is as follows -
ECHO %1
If a file name contains % eg. "% of STATS.txt", the output ends up being
of STATS.txt
Which is wrong. I have tried using Setlocal DisableDelayedExpansion but with little success
Setlocal DisableDelayedExpansion
for /R %%a in (*.*) do (
SET "var=%%~a"
Setlocal EnableDelayedExpansion
call TEST_UPGRADE "%var%" "%%~a"
)
There are other stackoverflow answers, but they all need the % character to be known before hand. Since the file names are not in our control, these solutions won't work for us. Is there any way of handling this?
Thanks!
platform: cmd.exe for Windows XP
Aacini shows a solution that would work with % and also ! but it fails with carets ^.
But the solution is simple.
First it's necessary to disable the delayed expansion to handle the exclamation marks.
The filename is now exactly in the var variable.
The problems with carets and percents are caused by the CALL.
This can be solved with the CALL itself by use only the second percent expansion phase of the CALL by using %%var%%.
Setlocal DisableDelayedExpansion
for /R %%a in (*.*) do (
SET "var=%%~a"
call TEST_UPGRADE "%%var%%"
)
The next problem is in the second.bat to display the filename.
This should be done with delayed expansion enabled to avoid problems with special characters, or you need always quotes.
set "var=%~1"
setlocal EnableDelayedExpansion
echo Filename: !var!
solution with a temp file:
first.bat
#ECHO OFF &SETLOCAL
REM to escape the '%' use a second '%'
SET "var=40%% &off!.txt"
REM get a random temp file name
:loop
SET "tname=%temp%%random%%random%"
IF EXIST "%tname%" GOTO :loop
SETLOCAL ENABLEDELAYEDEXPANSION
REM save the variable in the file
>"%tname%" (ECHO(!var!)
CALL "second.bat" "%tname%"
ENDLOCAL
second.bat
#ECHO OFF &SETLOCAL
SET "tname=%~1"
<"%tname%" set/p"var="
SETLOCAL ENABLEDELAYEDEXPANSION
ECHO !var!
DEL "%tname%" /F /Q
..output is:
40% &off!.txt
EDIT: I added the enable/disable delayed expansion technique to avoid problems with exclamation-mark character.
#echo off
setlocal DisableDelayedExpansion
for /F "delims=" %%a in ('dir /B *.txt') do echo %%a
echo/
for %%a in (*.txt) do (
SET "var=%%a"
setlocal EnableDelayedExpansion
call :TEST_UPGRADE "!var:%%=%%%%!" "%%~a"
endlocal
)
goto :EOF
:TEST_UPGRADE
ECHO First: %1 Second: %2
exit /B
Output example:
% of STATS.txt
Discount of 10% in all.txt
Normal file.txt
First: "% of STATS.txt" Second: " of STATS.txt"
First: "Discount of 10% in all.txt" Second: "Discount of 10 in all.txt"
First: "Normal file.txt" Second: "Normal file.txt"

Resources