existing A.bat :
rem set variable pathVariable to appropriate value
set pathVariable=../Doc/English/MyDoc.htm
rem asd
from B.bat, I need to update the value of pathVariable with a path containing spaces, but after replacing spaces with %20 So after running B.bat, A.bat should look like :
rem set variable pathVariable to appropriate value
set pathVariable=C:/Program%20Files/XXX%20YYY/MyDoc.htm
rem asd
I tried to play with this and could write
#echo off
setlocal enabledelayedexpansion
set inputFile=A.bat
set outputFile=A_New.bat
set pathVar=../Doc/English/MyDoc.htm
set newPathVarSpace=C:/Program Files/XXX YYY/MyDoc.htm
set space=%%20
set newPathVarNoSpace=%newPathVarSpace: =!space!%
echo %newPathVarNoSpace%
for /f "tokens=1,* delims=" %%A in ( '"type %inputFile%"') do (
SET line=%%A
rem SET modified=!string:%pathVar%=%newPathVarSpace%!
SET modifiedLine=!line:%pathVar%=%newPathVarNoSpace%!
echo !modifiedLine! >> %outputFile%
)
The script works but its eating all the blank lines which I want to preserve.
Thanks for your help.
Try below piece of code -
A.BAT
rem set variable pathVariable to appropriate value.
pathVariable=C:\Test
B.BAT
#echo off
setlocal enableextensions disabledelayedexpansion
set "config=.\A.bat"
set "path=C:\Batch projects\Batch tests\bin\Debug App"
for /f "tokens=*" %%l in ('type "%config%"^&cd.^>"%config%"'
) do for /f "tokens=1 delims== " %%a in ("%%~l"
) do if /i "%%~a"=="pathVariable" (
>>"%config%" echo(pathVariable=%path%
) else (
>>"%config%" echo(%%l
)
type "%config%"
endlocal
Now go to A.BAT, Open it with Notepad and check the pathVariable Value as below -
C:\Batch projects\Batch tests\bin\Debug App
Related
I made this code
dir /B /S %RepToRead% > %FileName%
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo %z%
echo %%a
)
echo %%a is working fine but echo %z% returns "echo disabled".
I need to set a %z% because I want to split the variable like %z:~7%
Any ideas?
There are two methods to setting and using variables within for loops and parentheses scope.
setlocal enabledelayedexpansion see setlocal /? for help. This only works on XP/2000 or newer versions of Windows.
then use !variable! instead of %variable% inside the loop...
Create a batch function using batch goto labels :Label.
Example:
for /F "tokens=*" %%a in ('type %FileName%') do call :Foo %%a
goto End
:Foo
set z=%1
echo %z%
echo %1
goto :eof
:End
Batch functions are very useful mechanism.
You probably want SETLOCAL ENABLEDELAYEDEXPANSION. See https://devblogs.microsoft.com/oldnewthing/20060823-00/?p=29993 for details.
Basically: Normal %variables% are expanded right aftercmd.exe reads the command. In your case the "command" is the whole
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo %z%
echo %%a
)
loop. At that point z has no value yet, so echo %z% turns into echo. Then the loop is executed and z is set, but its value isn't used anymore.
SETLOCAL ENABLEDELAYEDEXPANSION enables an additional syntax, !variable!. This also expands variables but it only does so right before each (sub-)command is executed.
SETLOCAL ENABLEDELAYEDEXPANSION
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo !z!
echo %%a
)
This gives you the current value of z each time the echo runs.
I struggeld for many hours on this.
This is my loop to register command line vars.
Example : Register.bat /param1:value1 /param2:value2
What is does, is loop all the commandline params,
and that set the variable with the proper name to the value.
After that, you can just use
set value=!param1!
set value2=!param2!
regardless the sequence the params are given. (so called named parameters).
Note the !<>!, instead of the %<>%.
SETLOCAL ENABLEDELAYEDEXPANSION
FOR %%P IN (%*) DO (
call :processParam %%P
)
goto:End
:processParam [%1 - param]
#echo "processparam : %1"
FOR /F "tokens=1,2 delims=:" %%G IN ("%1") DO (
#echo a,b %%G %%H
set nameWithSlash=%%G
set name=!nameWithSlash:~1!
#echo n=!name!
set value=%%H
set !name!=!value!
)
goto :eof
:End
Simple example of batch code using %var%, !var!, and %%.
In this example code, focus here is that we want to capture a start time using the built in variable TIME (using time because it always changes automatically):
Code:
#echo off
setlocal enabledelayedexpansion
SET "SERVICES_LIST=MMS ARSM MMS2"
SET START=%TIME%
SET "LAST_SERVICE="
for %%A in (%SERVICES_LIST%) do (
SET START=!TIME!
CALL :SOME_FUNCTION %%A
SET "LAST_SERVICE=%%A"
ping -n 5 127.0.0.1 > NUL
SET OTHER=!START!
if !OTHER! EQU !START! (
echo !OTHER! is equal to !START! as expected
) ELSE (
echo NOTHING
)
)
ECHO Last service run was %LAST_SERVICE%
:: Function declared like this
:SOME_FUNCTION
echo Running: %1
EXIT /B 0
Comments on code:
Use enabledelayedexpansion
The first three SET lines are typical
uses of the SET command, use this most of the time.
The next line is a for loop, must use %%A for iteration, then %%B if a loop inside it
etc.. You can not use long variable names.
To access a changed variable such as the time variable, you must use !! or set with !! (have enableddelayexpansion enabled).
When looping in for loop each iteration is accessed as the %%A variable.
The code in the for loop is point out the various ways to set a variable. Looking at 'SET OTHER=!START!', if you were to change to SET OTHER=%START% you will see why !! is needed. (hint: you will see NOTHING) output.
In short !! is more likely needed inside of loops, %var% in general, %% always a for loop.
Further reading
Use the following links to determine why in more detail:
Difference between %variable% and !variable! in batch file
Variable usage in batch file
To expand on the answer I came here to get a better understanding so I wrote this that can explain it and helped me too.
It has the setlocal DisableDelayedExpansion in there so you can locally set this as you wish between the setlocal EnableDelayedExpansion and it.
#echo off
title %~nx0
for /f "tokens=*" %%A in ("Some Thing") do (
setlocal EnableDelayedExpansion
set z=%%A
echo !z! Echoing the assigned variable in setlocal scope.
echo %%A Echoing the variable in local scope.
setlocal DisableDelayedExpansion
echo !z! &rem !z! Neither of these now work, which makes sense.
echo %z% &rem ECHO is off. Neither of these now work, which makes sense.
echo %%A Echoing the variable in its local scope, will always work.
)
set list = a1-2019 a3-2018 a4-2017
setlocal enabledelayedexpansion
set backup=
set bb1=
for /d %%d in (%list%) do (
set td=%%d
set x=!td!
set y=!td!
set y=!y:~-4!
if !y! gtr !bb1! (
set bb1=!y!
set backup=!x!
)
)
rem: backup will be 2019
echo %backup%
Try this:
setlocal EnableDelayedExpansion
...
for /F "tokens=*" %%a in ('type %FileName%') do (
set z=%%a
echo !z!
echo %%a
)
You can use a macro if you access a variable outside the scope
#echo off
::Define macro
set "sset=set"
for /l %%a in (1,1,4) do (
::set in loop
%sset% /a "x[%%a]=%%a*%%a"
if %%a equ 4 (
:: set in condition
%sset% "x[%%a]=x Condition"
%sset% "y=y Condition"
)
)
echo x1=%x[1]% x2=%x[2]% x3=%x[3]% x4=%x[4]% y=%y%
:: Bonus. enableDelayedExpansion used to access massive from the loop
setlocal enableDelayedExpansion
echo Echo from the loop
for /l %%a in (1,1,4) do (
::echo in one line - echo|set /p =
echo|set /p "=x%%a=!x[%%a]! "
if %%a equ 4 echo y=%y%
)
pause
I know this isn't what's asked but I benefited from this method, when trying to set a variable within a "loop". Uses an array. Alternative implementation option.
SETLOCAL ENABLEDELAYEDEXPANSION
...
set Services[0]=SERVICE1
set Services[1]=SERVICE2
set Services[2]=SERVICE3
set "i=0"
:ServicesLoop
if defined Services[%i%] (
set SERVICE=!Services[%i%]!
echo CurrentService: !SERVICE!
set /a "i+=1"
GOTO :ServicesLoop
)
The following should work:
setlocal EnableDelayedExpansion
for /F "tokens=*" %%a in ('type %FileName%') do (
set "z=%%a"
echo %z%
echo %%a
)
I have a CSV file with leading-and-trailing doublequotes per line I want to remove, and made a DOS batch to do it. The following works for an explicit path:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=*" %%A in (C:\Folder\WrappedInQuotes.csv) do (
set line=%%A
echo !line:~1,-1! >> C:\Folder\UnWrapped.csv
)
Of course, if the path has spaces in it, the following will not work:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=*" %%A in (C:\Folder\Sub Folder\WrappedInQuotes.csv) do (
set line=%%A
echo !line:~1,-1! >> C:\Folder\Sub Folder\UnWrapped.csv
)
(#echo on, the message is "...cannot find the file C:\Folder\Sub", of course)
As a next-step test, I simply wrapped the two explicit filespecs in doublequotes:
#echo off
setlocal enabledelayedexpansion
for /F "tokens=*" %%A in ("C:\Folder\Sub Folder\WrappedInQuotes.csv") do (
set line=%%A
echo !line:~1,-1! >> "C:\Folder\Sub Folder\UnWrapped.csv"
)
With #echo on, the For seems to be getting the correct filespec (original CSV), but now the destination CSV has
:\Folder\Sub Folder\EachLineWrappedInQuotes.cs
(the source CSV full filespec, with first and last characters removed), instead of the contents of the source CSV with first and last characters (the doublequote wrapping) removed.
Ultimately, I want to replace the explicit paths with a path variable like %~dp0, but haven't been able to get past the "next-step test".
(I have tried to solve this by studying the many answers already given, with no success, sorry!)
To get the content of the file and remove double quotes, without the need to set variables, set usebackq
method 1:
#echo off
for /F "usebackq tokens=*" %%A in ("C:\Folder\Sub Folder\WrappedInQuotes.csv") do (
echo %%~A >> "C:\Folder\Sub Folder\UnWrapped.csv"
)
method 2, if you still want to set the variable:
#echo off
setlocal enabledelayedexpansion
for /F "usebackq tokens=*" %%A in ("C:\Folder\Sub Folder\WrappedInQuotes.csv") do (
set line=%%~A
echo !line! >> "C:\Folder\Sub Folder\UnWrapped.csv"
)
Or by using type :
#echo off
for /F "tokens=*" %%A in ('type "C:\Folder\Sub Folder\WrappedInQuotes.csv"') do (
echo %%~A >> "C:\Folder\Sub Folder\UnWrapped.csv"
)
I am trying to write a windows Batch file to obtain below OUTPUT for given INPUT
INPUT:
//Dev-420/PAVAN/src/main/java/test/abcd/mnop/HealthCheck.java - edit change 1111111
//Dev-420/PAVAN/src/main/java/test/abcd/mnop/HealthStatus.java - edit change 1111111
//Dev-420/PAVAN/src/main/java/test/xyz/Relations.java - edit change 1111111
OUTPUT:
target/classes/test/abcd/mnop/, target/classes/test/abcd/mnop/, target/classes/test/xyz
Below is the script I used, however replacing filename is not working.
#echo off
set "File2Read=files_list.tmp"
SET "BINARY_PATH="
set "FILENAME="
setlocal EnableDelayedExpansion
set "BINARY_FILENAME="
set "lastPart="
set "replaceBinaryPath=target/classes/"
SET "replaceBinaryFileName=,"
set "basePath=//ATT/Dev-420/PAVAN/src/main/java/"
for /f "delims=" %%a in ('Type "%File2Read%"') do (
set "line=%%a"
for /f "tokens=1,2,3,4,5 delims= " %%a in ("!line!") do set FILENAME=%%a
set "BINARY_FILENAME=!FILENAME:%basePath%=%replaceBinaryPath%!"
if not !FILENAME!==!BINARY_FILENAME! (
for %%a in ("!BINARY_FILENAME!/.") do set "lastPart=%%~nxa"
set "BINARY_PATH=!BINARY_FILENAME:!lastPart!=%replaceBinaryFileName%!"
echo !BINARY_PATH!
)
)
endLocal
here, everything works as expected, except below statement,
set "BINARY_PATH=!BINARY_FILENAME:!lastPart!=%replaceBinaryFileName%!"
Since ‘lastPart’ will be the dynamically changing-value, in order to replace it with ‘comma’ It was supposed to work with !lastPart! but its not working and output is word ‘lastPart’
We cant use %lastPart% as it is dynamic variable.
Please help me with replacing a dynamic string with 'comma'.
Please help me out here!
You could use the %%~nxa expression directly, I only changed the parameter name to %%C
..
for /f "delims=" %%a in ('Type "%File2Read%"') do (
set "line=%%a"
for /f "tokens=1,2,3,4,5 delims= " %%a in ("!line!") do set FILENAME=%%a
set "BINARY_FILENAME=!FILENAME:%basePath%=%replaceBinaryPath%!"
if not !FILENAME!==!BINARY_FILENAME! (
for %%C in ("!BINARY_FILENAME!/.") do (
set "BINARY_PATH=!BINARY_FILENAME:%%~nxC=%replaceBinaryFileName%!"
echo !BINARY_PATH!
)
)
)
As #jeb's version didn't work for me, here an alternative
as the usage of %%~dpa changes the the non windows path separator / to \ it is corrected.
:: Q:\Test\2018\09\24\SO_52482593.cmd
#echo off & setlocal EnableDelayedExpansion
set "File2Read=files_list.tmp"
set "BINARY_PATH="
set "replaceBinaryPath=target/classes/"
set "replaceBinaryFileName=, "
set "Output="
for /f %%a in ('Type "%File2Read%"') do (
for /f "tokens=5* delims=\/" %%b in ("%%~dpa") do (
Set "Output=!Output!%replaceBinaryFileName%%replaceBinaryPath%%%c"
)
)
Set "Output=%Output:\=/%"
Echo %Output:~2%
endLocal
Sample output:
> Q:\Test\2018\09\24\SO_52482593.cmd
target/classes/test/abcd/mnop/, target/classes/test/abcd/mnop/, target/classes/test/xyz/
I'm trying to set a variable (Let's say, filehash is the variable name) from a file using batch file. Alas, I was stuck facing these two problems:
When it contains special characters, especially exclamation mark(s) as I'm using enableDelayedExpansion.
While doing that, I need to change & to & as well.
I've tried several solutions provided from various sources but none would fit my requirements.
Here's my current code:
#echo off
set grep=binaries\grep.exe
set fileindex=binaries\index.htm
set count=0
for /f "tokens=* delims=" %%a in (crc.dat) do (
set count=!count! + 1
set filehash=%%a
%grep% --ignore-case -w "!filehash!" %fileindex%>> list.dat
)
And an example of what's inside the crc.dat file:
Kabooom! Kablooey!
Kaboom & Kablooey
And the result using my current code above in list.dat:
Kabooom Kablooey
Kaboom & Kablooey
The result that I'm expecting in list.dat:
Kabooom! Kablooey!
Kaboom & Kablooey
I hope I conveyed my problem properly and thank you in advance!
To replace & by & in the input of grep, use this:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "grep=binaries\grep.exe"
set "fileindex=binaries\index.htm"
set "file=crc.dat"
set "list=list.dat"
rem // Initialise counter:
set /A "count=0"
> "%list%" (
for /F "usebackq delims=" %%a in ("%file%") do (
rem // Increment counter:
set /A "count+=1"
rem // Assign line string to variable:
set "lineitem=%%a"
rem // Toggle delayed expansion:
setlocal EnableDelayedExpansion
rem // Do sub-string replacement:
set "lineitem=!lineitem:&=&!"
rem // Execute `grep` command line:
"!grep!" --ignore-case -w "!lineitem!" "!fileindex!"
endlocal
)
)
rem // Return counter:
echo/%count%
endlocal
To replace & by & in the output of grep, use this:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Define constants here:
set "grep=binaries\grep.exe"
set "fileindex=binaries\index.htm"
set "file=crc.dat"
set "list=list.dat"
rem // Initialise counter:
set /A "count=0"
> "%list%" (
for /F "usebackq delims=" %%a in ("%file%") do (
rem // Increment counter:
set /A "count+=1"
rem // Execute `grep` command line and capture its output by `for /F`:
for /F "delims=" %%b in ('^""%grep%" --ignore-case -w "%%a" "%fileindex%"^"') do (
rem // Assign `grep` output to variable:
set "lineitem=%%b"
rem // Toggle delayed expansion:
setlocal EnableDelayedExpansion
rem // Do sub-string replacement:
set "lineitem=!lineitem:&=&!"
rem // Return modified string:
echo(!lineitem!
endlocal
)
)
)
rem // Return counter:
echo/%count%
endlocal
In general, to handle strings with exclamation marks, you must toggle delayed expansion, so that normal %-expanded variables and for variable references like %%a become expanded with delayed expansion disabled.
This is a solution which is delayedExpansion-free and able to replace & to &.
#echo off
set grep=binaries\grep.exe
set fileindex=binaries\index.htm
set count=0
for /f "tokens=* delims=" %%a in (crc.dat) do (
set /a count+=1
%grep% --ignore-case -w "%%a" %fileindex%>>temp.dat
)
powershell -Command "(gc temp.dat) -replace '&', '&' | sc list.dat"
del /f temp.dat
pause
exit /b
Some changed things:
set /a count+=1 = set /a count=%count%+1
The !fileHash! points to %%a, so why do we need it? %%a will work.
The powershell command replaces & with &.
Output the replaced content into the file.
Delete a temp file used.
I am parsing an xml file its format is like:
<ResourcePicture Name="a.jpg">
<GeneratedPicture Name="b.jpg"/>
<GeneratedPicture Name="c.jpg"/>
</ResourcePicture>
I can print each name of the pictures but I want to check something with an if statement inside there. However I get an error "< was unexpected at this time." but when I remove the if statement, that works just as fine. So what am I missing? Thanks in advance.
set "xmlFile=pictures.xml"
REM split xml file into lines
for /f "tokens=* skip=2" %%a in (%xmlFile%) do (
REM %%a contais a string like <ResourcePicture Name="a.jpg">
set "currnetLine=%%a"
set "currnetLine=!currnetLine:"=+!"
set counter=0
for /f "delims=+ tokens=2" %%c in ("!currnetLine!") do (
REM %%c contains the picture name like a.jpg
set /a counter=counter+1
REM CHECKING SOMETHING
if not %counter%==1 ( echo abc )
echo %%c
)
)
you need delayed expansion (I dont know if the logic of the script achieves what you want but like this it has no errors):
#echo off
set "xmlFile=pictures.xml"
REM split xml file into lines
setlocal enableDelayedExpansion
for /f "tokens=* skip=2" %%a in (%xmlFile%) do (
REM %%a contais a string like <ResourcePicture Name="a.jpg">
set "currnetLine=%%a"
set "currnetLine=!currnetLine:"=+!"
set counter=0
for /f "delims=+ tokens=2" %%c in ("!currnetLine!") do (
REM %%c contains the picture name like a.jpg
set /a counter=counter+1
REM CHECKING SOMETHING
if not !counter! == 1 ( echo abc )
echo %%c
)
)