How to solve this batch glitch? - batch-file

I have a little problem in my code,
if I
set ghot=1
and
set fo1=text
and try echoing
echo %fo%ghot%%
like this, it comes like
%fo1%
instead of text

I misunderstood what you were asking at first. Adding call to the line will give you the behavior you want.
call echo %%fo%ghot%%%
Edited to add the extra enclosing %'s It works without them from the command line, but not from within a batch file.

An alternative method using delayed expansion:
#Echo Off
SetLocal EnableDelayedExpansion
Set "ghot=1"
Set "fo1=text"
Echo=!fo%ghot%!
Timeout -1

Related

Use a variable on SET in Windows batch file

I´m trying to use a variable instead of a fixed number here:
set PACK_VERSION=Testing12345
set PACK_VERSION=%PACK_VERSION:~7,100%
echo %PACK_VERSION%
Instead of this number 7, I would like to use a variable, something like this:
set VARNUM=7
set PACK_VERSION=Testing12345
set PACK_VERSION=%PACK_VERSION:~%VARNUM%,100%
echo %PACK_VERSION%
I don´t know how to insert that properly, anyone can help? Thanks!
The "usual" way is using delayed expansion:
setlocal enabledelayedexpansion
set VARNUM=7
set PACK_VERSION=Testing12345
set PACK_VERSION=!PACK_VERSION:~%VARNUM%!
echo %PACK_VERSION%
but there is also a little trick to do it without delayed expansion (you have to parse the line twice, call is a good method to do so):
set VARNUM=7
set PACK_VERSION=Testing12345
call set PACK_VERSION=%%PACK_VERSION:~%VARNUM%%%
echo %PACK_VERSION%

How to refer to a variable in Batch Scripting?

Imagine a script called batch.bat, invoked like this:
batch.bat Two
The script contains:
set One=1
set Two=2
set Three=3
set Choice=%1
echo %Choice%
But I want to echo 2, not Two.
What elegant way can I employ to do that? I thought about if %Choice%=One, etc. but my actual script is a bit more complex than the example provided.
Edit: I also tried:
set percent=%%
echo %percent%%Choice%%percent%
But it won't treat the resulting expression as a variable reference.
#echo off
setlocal EnableDelayedExpansion
set one=1
set c=%1
echo delayed expansion and variable: !%c%!
echo delayed expansion and paramr: !%1!
call echo using call and variable: %%%c%%%
call echo using call and param: %%%1%%
I personally prefer the delayed expansion method, but sometimes there are reasons to look for an alternative.
OK, I have figured it out:
The key is to use the "set delayed expansion" trick.
There's also a trick using the "call set" instead of the above but I reckon if I use that, the next guy after me won't know what I was trying to do and might get in trouble.
The script can be fixed by adding !! around the reference that we want to force into the variable name, like so:
#echo off
setlocal EnableDelayedExpansion
set One=1
set Two=2
set Three=3
set Choice=!%1!
echo %Choice%

set PATH with multiple lines

In a Batch file I need to add some paths to the PATH env variable. Since its a larger numer of long paths I tried to spread them on multiple line and tried to make the bat-file as clean as I can by indenting the lines.
But it seems that the spaces at the beginning of the newline (and so in the %PATH%) are interpreted as part of the actual path.
So
SET PATH=^
\\somewhere\Tools\strawberryperl\perl\site\bin;^
\\somewhere\Tools\strawberryperl\perl\bin;^
\\somewhere\Tools\strawberryperl\c\bin;^
\\somewhere\Tools\KDiff3;^
%PATH%
does not work (programs are not found). Is there some trick I can use?
Because it is a medium complex batch file some indentation would be nice.
for %%x in (
"\\somewhere\Tools\strawberryperl\perl\site\bin;"
"\\somewhere\Tools\strawberryperl\perl\bin;"
"\\somewhere\Tools\strawberryperl\c\bin;"
"\\somewhere\Tools\KDiff3;"
) do call set "path=%%path%%%%~x"
this will append the extra items to the path. You'd need to initialise path to nothing first if all you want is to build the directory sequence specified.
There is no way to have PATH ignore the leading spaces. I see two possible options if you want indented lines:
Option 1 - Use undefined variable to indent, so spaces never get in the value
#echo off
SET PATH=^
% =%\\somewhere\Tools\strawberryperl\perl\site\bin;^
% =%\\somewhere\Tools\strawberryperl\perl\bin;^
% =%\\somewhere\Tools\strawberryperl\c\bin;^
% =%\\somewhere\Tools\KDiff3;^
% =%%PATH%
Option 2 - Remove the spaces afterwards
#echo off
SET PATH=^
\\somewhere\Tools\strawberryperl\perl\site\bin;^
\\somewhere\Tools\strawberryperl\perl\bin;^
\\somewhere\Tools\strawberryperl\c\bin;^
\\somewhere\Tools\KDiff3;^
%PATH%
set "PATH=%PATH:; =%"
First let me start by informing you that adding to the PATH variable in this way is ONLY for the running session. Once the cmd session is closed that variable returns to its previous value.
Here are a suggestion, append each addition one by one:
SET "ToAdd=\\somewhere\Tools\strawberryperl\perl\site\bin;"
SET "ToAdd=%ToAdd%;\\somewhere\Tools\strawberryperl\perl\bin;"
SET "ToAdd=%ToAdd%;\\somewhere\Tools\strawberryperl\c\bin;"
SET "ToAdd=%ToAdd%;\\somewhere\Tools\KDiff3"
SET "PATH=%PATH%;%ToAdd%"
BTW, if you were hoping to add to the environment variable beyond the running session then it is important that you ignore anyone suggesting you use SETX instead of SET. (the variable will be truncated at 1024 bytes therefore corrupting it). Your best solutions would involve editing the registry and possibly using a built in tool such as powershell.
Edit
This shows the method mentioned in my comment and uses the same structure as Magoo's answer:
C:\MyDir\Paths.txt
\\somewhere\Tools\strawberryperl\perl\site\bin
\\somewhere\Tools\strawberryperl\perl\bin
\\somewhere\Tools\strawberryperl\c\bin
\\somewhere\Tools\KDiff3
batch file
#Echo Off
SetLocal EnableDelayedExpansion
For /F "UseBackQDelims=" %%A In ("C:\MyDir\paths.txt") Do Set "Path=!Path!;%%~A"
Echo(%Path%
EndLocal
Timeout -1
This means that you only really need to include the for loop each time instead of adding each of the paths to it.
Not even remotely bulletproof, but the Magoo's answer reminded me this. Just because someone, somewhere, could find a better usage for this construct
#echo off
setlocal enableextensions disabledelayedexpansion
for /f "delims=" %%a in ('echo "%path:;=" "%"
"\\somewhere\Tools\strawberryperl\perl\site\bin"
"\\somewhere\Tools\strawberryperl\perl\bin"
"\\somewhere\Tools\strawberryperl\c\bin"
"\\somewhere\Tools\KDiff3"
""') do (set "path=%%~a") & call set "path=%%path:" "=;%%"
path

Replace a substring in batch script

I have three variables: string, search, replace. I wish to substitute the %search% in %string% with %replace%.
This works but needs hard characters.
SET modified=%string:morning=evening%
This seems to be answer in the forums but does not work. It simply stores the entire line at %modified%
SET modified=!string:%search%=%replace%!
The ! format is doing delayed expansion--the % variables get expanded immediately, but the ! variable gets expanded only when it's needed. I believe that only works in a batch file, so if you're experimenting directly at the command line you won't get the same behaviour as if you are running a batch file.
Make sure to enable delayed expansion in your batch file before using the ! notation, like this:
SETLOCAL ENABLEDELAYEDEXPANSION
SET string=This morning
SET search=morning
SET replace=evening
SET modified=!string:%search%=%replace%!
ECHO %modified%
ENDLOCAL
This will echo This evening.

variable in variable in batch and delayed expansion

I'm trying to use variable in variable in conjunction with delayed expansion but still no luck.
SETLOCAL EnableDelayedExpansion
SET ERROR_COMMAND=exit /B ^!ERRORLEVEL^!
This is my last try. I want to setup an ERROR_COMMAND to be called when one of the steps in batch file crashes. The command is supposed to be:
IF ERRORLEVEL 1 !ERROR_COMMAND!
or
IF ERRORLEVEL 1 %ERROR_COMMAND%
The thing is, I'm not able to find out, how to SET properly the ERROR_COMMAND variable, so that ERRORLEVEL is not evaluated at the time of assignment, but at the time of evaluating the variable
Of course I can copy&paste the code all over the batch file, but using the variable just seems a bit prettier...
Anyone?
Thanks, Milan
I'm sure there are many ways to do this, here are two:
A)
SET ERROR_COMMAND=call echo.errlvl=%%ERRORLEVEL%%
verify failthis 2>nul
%ERROR_COMMAND%
B)
setlocal DISABLEDELAYEDEXPANSION&set "X=!"
call (endlocal&set "ERROR_COMMAND=echo.errlvl=%X%ERRORLEVEL%X%")&setlocal ENABLEDELAYEDEXPANSION
verify failthis 2>nul
%ERROR_COMMAND%
It should also be noted that if someone does set ERRORLEVEL=foo (In your script or "globally"), %ERRORLEVEL% will not resolve correctly (Same goes for %CD% and all the other built in special variables)

Resources