Batch file set /p expressions - windows

I'm attempting to make the errorlevel environment variable increase by one every time a certain section of my code is ran. I read in set /? that you can use /p to list an expression that needs to be calculated after the equals sign, however it doesn't seem to change the errorlevel at all.
This is what I have.
if not %cd2%==%cd1% (goto :installauto) else set /p errorlevel=(%errorlevel%+1)
Thanks for the help, and sorry if this is a noob question. >.<
EDIT: Wow, I'm an idiot. The /a tag is used for expressions. Sorry lol.

It's a bad idea to change/create an errorlevel variable, as this is not the errorlevel for other programs.
Then you can not access the "real" errorlevel anymore.
You could better do this with an other variable and exit the bacth file with exit /B
set myErr=0
if not %cd2%==%cd1% (
goto :installauto
) else (
set /a myErr=myErr+1
)
exit /b %myErr%

Related

If statement ( was unexpected at this time

I have a bundled if statement that checks whether java is installed and whether or not i'm at college or at home it is part of a larger piece of code but doesn't work on its own either any help would be much appreciated
Triple Checked i have the right number of brackets and equals signs and making sure no obvious mistakes were made so i'm confused as to what has gone wrong
if exist 'C:\Temporary Workspace' (set installtype=College)
where java >nul 2>nul
pause
if %errorlevel%==1 (
if %installtype%==College (
goto :college
) else (
set /P javaboolean=Java was not found is java installed? (Y/N)
if %javaboolean%==Y (
echo Please enter the path to java.exe
set /P javalocation=e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe
)
)
)
pause
exit
:college
echo success for college detection
pause
The error message and run time:
D:\Batch Testing>echo Checking Location...
Checking Location...
D:\Batch Testing>if exist 'C:\Temporary Workspace' (set installtype=College)
D:\Batch Testing>where java 1>nul 2>nul
D:\Batch Testing>pause
Press any key to continue . . .
( was unexpected at this time.
I expect the output to be 'success for college detection' as the directory does exist
you need to change your ifs a little bit
the first could be changed to
if exist "C:\Temporary Workspace" set installtype=College
note that the single apostrophe is not a valid quotation mark in windows cmd. And you can remove your parentheses because they are not needed.
the second could be written as
if errorlevel 1 (
because errorlevel is not %errorlevel% (for a detailed explanation, read https://devblogs.microsoft.com/oldnewthing/20080926-00/?p=20743 )
and the last could be
if .%installtype%==.College (
because when installtype is blank the if instruction makes no sense and produces syntax error; inserting the two . avoids it.
... and, as a bonus, you might want to consider to use if /i to ignore case when comparing, so College, college, COLLEGE or even cOllegE would match.
Well, there are several issues in your code. The line
if exist 'C:\Temporary Workspace' (set installtype=College)
will never set the variable installtype, because this checks whether 'C:\Temporary exists, which does not, since the apostrope ' is just an ordinary character for the Windows Command Prompt cmd. To make it work you must use quotation marks ":
if exist "C:\Temporary Workspace\" (set "installtype=College")
The trailing \ lets the condition check for existence of a directory called Temporary Workspace but not for a file with that name.
Note that I used the quoted set syntax here, which is generally recommended as it protects special characters.
The condition
if %installtype%==College (
will return a syntax error, because the variable installtype has not been set before (due to the wrong syntax you used). To avoid trouble with empty variables, quote both comparison expressions:
if "%installtype%"=="College" (
This is also described in this thread.
The command
set /P javaboolean=Java was not found is java installed? (Y/N)
will fail when in a parenthesised block of code, because the ) will unintentionally be recognised by cmd and close the block at an undesired position. Again use quotation to solve that:
set /P javaboolean="Java was not found is java installed? (Y/N)"
or:
set /P "javaboolean=Java was not found is java installed? (Y/N)"
However, the condition
if %javaboolean%==Y (
will still fail, because the queried variable javaboolean is set in the same block of code, so the returned value is the one present when the entire block is parsed, which is an empty string most probably. To overcome this, you must apply delayed variable expansion.
Put this somewhere before to enable delayed expansion:
setlocal EnableDelayedExpansion
Then replace the %-signs by exclamation marks ! (as you can see I again applied quotation here):
if "!javaboolean!"=="Y" (
Then put this somewhere after to end the environment localisation introduced by setlocal:
endlocal
Regard that all environment changes (variables, current directories) after setlocal are lost after endlocal and the state before setlocal becomes restored.
A similar problem is also described in this question and solved by this answer.
Instead of set /P just for a Yes/No decision consider to use the choice command, which does not allow to enter anything else:
rem /* The default choices are `Y` and `N`;
rem `choice` sets `ErrorLevel` to `1` when pressing `Y` and to `2` when pressing `N`: */
choice /M "Java was not found is java installed"
rem // The following means: if ErrorLevel >= 1 and if ErrorLevel < 2:
if ErrorLevel 1 if not ErrorLevel 2 (echo Yes has been chosen.)
Instead of
exit
you should use
exit /B
to only terminate the batch script but keep the hosting cmd instance alive. This is particularly helpful when you execute the batch file from a Command Prompt window rather than by double-clicking its icon in Explorer as you can view the console output then.
Instead of the string comparison
if %errorlevel%==1 (
you could also do true numeric comparison like
if %errorlevel% equ 1 (
or, if you are fine with the condition to be true if ErrorLevel is also greater than one,
if ErrorLevel 1 (
Alternatively, you could even use condition execution operators, which query the exit code:
where java > nul 2>&1 && (
rem // The code here is executed when `where` succeeds.
) || (
rem // The code here is executed when `where` fails.
)
So finally, here is the fixed script:
Code based on yours:
if exist "C:\Temporary Workspace\" (set "installtype=College")
where java > nul 2>&1
pause
if ErrorLevel 1 (
if "%installtype%"=="College" (
goto :college
) else (
set /P javaboolean="Java was not found is java installed? (Y/N) "
setlocal EnableDelayedExpansion
if "!javaboolean!"=="Y" (
endlocal
echo Please enter the path to java.exe
set /P javalocation="e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe "
) else endlocal
)
)
pause
exit /B
:college
echo success for college detection
pause
Variant using conditional execution (||) and the choice command:
if exist "C:\Temporary Workspace\" (set "installtype=College")
where java > nul 2>&1 || (
if "%installtype%"=="College" (
goto :college
) else (
choice /M "Java was not found is java installed"
if ErrorLevel 1 if not ErrorLevel 2 (
echo Please enter the path to java.exe
set /P javalocation="e.g. C:\Program Files\Common Files\Oracle\Java\javapath\java.exe "
)
)
)
pause
exit /B
:college
echo success for college detection
pause

Windows Batch File Multiple labels back to back

In PHP or Javascript and other languages as well, there is the switch, case statement as a control flow tool. One of the neat features of that is it allows for multiple cases to be pointed to a single command group. For example:
switch(abc) {
case a:
case b:
case false:
console.log("hi")
break;
case c:
console.log("see ya")
break;
etc...
}
So that if abc is equal to a or b or is false, the "Hi" will be logged. Depending on the code, it can be a lot cleaner than calling from an object or tons of if else or if x || y || z statements.
I have a windows batch file where I'm doing the following:
GOTO %1
..... stuff
.... more stuff
REM =================LABELS BELOW==============
:-h
:--help
:-?
:--?
type help.txt
exit /b
It's more detailed than the above pseudocode, but that's the gist of it. It allows for aliases for the same argument And it works. If I execute mycmd -h or mycmd --help etc., I help the help file text displayed on the screen.
However, on the last line of my output, I get the error, THE SYSTEM CANNOT FIND THE BATCH LABEL SPECIFIED -.
The error might be caused by something else. I have some CALL commands and GOTO :EOF statements, so that certainly could be the source of the error.
But I've never seen the logic I applied above before used in a batch file, and I'm wondering if there are some other side effects that I might not be considering. Is it possible that I will encounter unpredictable side effects down the road? Is this bad practice for any reason?
Update:
I hadn't posted my code, because I think it's hard to read, and it's a work in progress. Basically, what you're seeing here is argument parsing. I'm parsing the passed values in to categories - imagine this example: node --file=d.js. I'm calling the --file the param, and the d.js the arg. And much of the code below is creating an array of each.
#echo off
SETLOCAL enabledelayedexpansion
#SET "T=%1"
IF /i NOT DEFINED T (GOTO -h)
SET /a counter=1
SET /a argCount=0
SET /a index=0
for %%x in (%*) do set /A argCount+=1
for /l %%x in (1,2,%argCount%) do (
call SET param[!index!]=%%!counter!
set /a counter+=2
SET /a index+=1
)
SET /A paramCount=!index!
SET /a counter=2
SET /a index=0
for /l %%x in (2,2,%argCount%) do (
call SET arg[!index!]="%%!counter!"
set /a counter+=2
SET /a index+=1
)
for /l %%i in (0,1,!paramCount!) do (
SET "arg=!ARG[%%i]!"
SET "p=!param[%%i]!"
CALL :!p! !arg!
)
GOTO END
:-h
:--help
:--?
:-?
type %~dp0\lib\help.txt
GOTO END
:--unzip
SET "a=%1"
IF /i NOT DEFINED a (
SET "MASK=\d+-[a-z]+.zip"
) ELSE if [%a%]==["all"] (
SET "MASK=\d+-[a-z]+.zip"
) else (
SET "MASK=!a!"
)
for /f "usebackq tokens=*" %%i in (`dir /a /b %dls%^|grep -iE "!MASK!"`) do (
#7z x %dls%\%%i -omypath\share\icons
)
GOTO :EOF
:END
#echo Done
ENDLOCAL
Update: I don't know if this will be helpful for anyone, but the problem was with SET /A paramCount=!index!. That let to always looking for a parameter with an argument no matter what, so that if my second parameter didn't have an argument, or neither did, it was causing problems. I 'solved' the problem by setting paramCount to !index!-1, but I think the upshot of this is that it's quite difficult to pass arbitrary, potentially optional, parameters to batch files, and probably should be parsed differently than I have done - or using a different coding language. That said, it's working fine now for what I need.

Changing variable values within If statements

I'm trying to take some user input defined variables to decide whether or not to enter the loop and execute a copy and rename followed by deletion of the original file as it will no longer be needed.
set /p multiTune="Does your tune file need to be shared with multiple
Element sequences? (y/n) "
Echo Multi Tune is %multiTune%
if "%multiTune%"=="y" (set /p tuneCount="How many sequences will need to share your tune file? ")
Echo Tune count is %tuneCount%
pause
if "%multiTune%"=="y" (SET /p tuneName="Enter the file letter/number combination for the R quant of your tune file. ") else (#ECHO The user specified there is no need for a second tune.)
Echo Tune Name is %tuneName%
pause
if "%multiTune%"=="y" (SET /a tuneCount+=1) else(set /a tuneCount-=tuneCount)
Echo Tune count is now %tuneCount%
pause
:loop
if "%tuneCount%"=="0" goto exitloop
Set /p seqNumber="Enter the number for one of the sequences."
copy %tuneName%.D.pdf "S%seqNumber%-TUN1_%tuneName%.D.pdf"
echo %tuneName%.D.pdf renamed to S%seqNumber%-TUN1_%tuneName%.D.pdf
pause
Set /a tuneCount-=1
if "%tuneCount%"=="1" DEL "%tuneName%.D.pdf"
if "%tuneCount%"==1 goto exitloop
Echo %tuneCount%
pause
goto loop
:exitloop
All of the echos and pauses are just for testing purposes to make sure I have the correct values in my variables.
The batch file runs fine with the variables containing the correct strings and values up until the line:
if "%multiTune%"=="y" (SET /a tuneCount+=1) else(set /a tuneCount-=tuneCount)
The file says something is unexpected and closes at this point so i havent gotten a chance to figure out if the looped portion even works. The point of the +1 is so that it enters the loop and executes the commands until it gets to 1 and skips the loop if it equals 0.
I read a bunch of information about setlocal delayedexpansion and using !'s around variables instead of %'s. I'm not sure how to implement this or if this applies to my problem at all. I know there is probably an easier way to do the if statements but I'm a novice and that was the easiest way for me to understand it as I've been learning on the fly through trial and error, and everything you see is the results of a single day of learning.
Any help would be much appreciated. I tried to be as detailed as possible about what it is I'm trying to do but if you have any questions I will do my best to answer.
I really think you are making the things so MUCH complicated...
Have a corrected piece of the code you provided us (Note: I did not touch the loop subroutine to be on-topic):
#echo off
choice /m "Does your tune file need to be shared with multiple element sequences? (y/n) " /C:yn /N
rem Echo Multi Tune is %errorlevel%
rem If errorlevel equals to 1 user input is "Y", it is 2 it is "N". (I commented the "echo" command as it changes the errorlevel value).
if errorlevel 2 goto question_N
if errorlevel 1 goto question_Y
:question_Y
set /p tuneCount="How many sequences will need to share your tune file? "
set /p tuneName="Enter the file letter/number combination for the R quant of your tune file. "
SET /a "tuneCount+=1"
goto loop
:question_N
set /p tuneCount="How many sequences will need to share your tune file? "
ECHO The user specified there is no need for a second tune.
set /a "tuneCount-=tuneCount"
goto loop
:loop
rem [Code you provided above]
I hope you are fine with this, testing it and it works!

Why I'm not being able to declare a variable inside a 'if exist' syntax in Batch (Windows) file?

In the following script few things won't work right and i'm having a hard time trying to figure the why, First it gives a 'Null' value to the variable (The .txt file is not empty), second it returns to me that some funcitons are not expected at that moment (Such as'goto' was not expected) so it maybe something with the syntax?
#echo off
set name1=sample1
set name2=sample2
set name3=sample3
set ccount=0
del mes.txt
:WFC
ping localhost -n 2 >nul
if exist mes.txt (
SetLocal EnableDelayedExpansion
set /p cname=<mes.txt
set /a ccount=%ccount%+1
if %cname%==!name%ccount%! goto AllowedList
if %ccount%==20 goto Crasher
goto WFC
I tryed calling echo %cname% in the end of the script and appareantly the var have a "nil" value, plus I also turned the #echo on and haven't found nothing useful to understand the problem.
The weirdest part is that if I take the variable declaration out of the 'if exist statemant', the whole script it works marvelously as in:
#echo off
set name1=sample1
set name2=sample2
set name3=sample3
set ccount=0
del mes.txt
:WFC
ping localhost -n 2 >nul
set /p cname=<mes.txt
if exist mes.txt (
SetLocal EnableDelayedExpansion
set /a ccount=%ccount%+1
if %cname%==!name%ccount%! goto AllowedList
if %ccount%==20 goto Crasher
goto WFC
So, this could be satisfying enough but it's not, there's a second software updating the mes.txt value all the time and I'm assuming that there will be some(not much, but some) cases in the second script where the var cname will get null value and still it will compare a null value with name1, completing excluding sample1 of the allowed lists. Can anyone solve this problem or at least explain the why?
Thankfully to the user MC ND, who awnsered me in the comments, I've managed to solve it, turns out that it was a really simple thing, his awnser was:
Your problem is delayed expansion (the lack of it) when reading %cname% and %ccount% (read here) – MC ND 24 mins ago
What I did to the script to make it work was:
#echo off
set name1=sample1
set name2=sample2
set name3=sample3
set ccount=0
del mes.txt
:WFC
ping localhost -n 2 >nul
set /p cname=<mes.txt
if exist mes.txt (
SetLocal EnableDelayedExpansion
set /a ccount=%ccount%+1
if !cname!==!name%ccount%! goto AllowedList
if !ccount!==20 goto Crasher
goto WFC
My guess is that it should be something more like this
:WFC
Timeout 1 1>Nul
If Not Exist mes.txt GoTo :WFC
SetLocal EnableDelayedExpansion
Set/P cname=<mes.txt
Set/A ccount+=1
If %ccount% Equ 20 GoTo :Crasher
If "!name%ccount%!" Equ "%cname%" GoTo :AllowedList
GoTo :WFC

Batch File not working for the given input

Following is the batch file that I have created, for any input its only showing is "NO INPUT PROVIDED" string, I tried searching on google and tried many things but non solved my problem.
#echo off
ECHO Please provide input... Valid input is :: Y/y (For changing path) or N/n (For not changing the path).
SETLOCAL
SET /p change=
if "%~1" equ "" GOTO ERROREND
if /I "%change%" equ "Y" GOTO YES
if /I "%change%" equ "N" GOTO NO
:YES
ECHO Y SELECTED.
GOTO SUCCESS
:NO
ECHO N SELECTED.
GOTO SUCCESS
:ERROREND
ECHO Input not recognized.
GOTO FAILURE
:SUCCESS
ECHO Task completed succcess fully.
pause
:FAILURE
ECHO NO INPUT PROVIDED.
pause
Help needed. Thank you for reading this question.
if "%~1" equ "" GOTO ERROREND
means 'if the first parameter to the batchfile is empty', so if you were to run this batch from the prompt as
yourbatchname something
then something is the first parameter.
You probably menat to use "%change%", not `"%~1".
Note: if not defined change is probably a better test.
Note: Simply pressing Enter when prompted by a set /p does not set the variable to empty. It leaves the value unchanged. Best to use
set "var="
set /p var=....
Note: batch simply charges on, instruction by instruction. It has no concept of 'end-of-procedure'. Consequently, if your entry is neither Y nor N (once you've got the %~1 issue resolved) batch will simply continue execution past the if statements to the next - the ECHO Y SELECTED.

Resources