CMD IF GTR statement not evaluating - if-statement

I am reading lines from a text file. I need to ignore the first half and after a certain line is reached, assign the lines read into a variable. The 2nd if statement never fulfills even though the output shows that q has incremented from 0 to 1.
Code:
set q=0
for /f "tokens=*" %%a in (myfilename) do (
if "%%a" == "# My Trigger Text" (
set /A "q+=1"
set q :: Debug Statement 1
echo %%a
)
if %q% GTR 0 (
set /A "q+=1"
set q :: Debug Statement 2
echo %%a
[Other code will eventually go here; nothing right now]
)
:: set q :: Debug Statement 3
)
pause
Output with Debug Statement 3 commented out shows:
ECHO is off.
q=1
# My Trigger Text
Press any key to continue...
If I uncomment Debug Statement 3, the output is:
ECHO is off.
q=0
q=0
q=0
q=0
q=0
q=0
q=1
# My Trigger Text
q=1
q=1
q=1
q=1
q=1
q=1
q=1
Press any key to continue...
So q is getting incremented the first time when it hits the trigger text, but it is not evaluating q to be greater than 0 to get inside the functional loop.

Related

Nested if in windows batch file cmd

I try to write some simple program in windows batch file. This program is similar to some simple application from "C programming language" Kernighan and Ritchie.
The task of this program is to count char numbers and words numbers. Belove there is a source code
rem Char Number and words number
#echo off
cls
echo ===============================================================
echo input strin
set /P a=
::set variables
set Temp_str=%a%
set /A charcounter = 0
set /A wordscounter = 0
:loop
if defined Temp_str (
set /P actual_char=%Temp_str:~0,1%
if %actual_char%=="" ( set /A wordscounter+=1 )
set Temp_str=%Temp_str:~1%
set /A charcounter+=1;
goto loop
)
echo %a% %charcounter% %wordscounter%
There is error somewher but I can't find it. I don't know what is wrong. I actually start with batch windows programming.
To debug batch files always disable #echo off otherwise you're flying blind
From there you'll see the issue is on the line
if %actual_char%=="" ( set /A wordscounter+=1 )
You need to add quotes.
if "%actual_char%"=="" ( set /A wordscounter+=1 )
In addition there are other issues with the code:
1).
set /P actual_char=%Temp_str:~0,1%
Should not have the /p option as you're not wanting to prompt the user to enter the character.
2) Your word counter should be checking for spaces in addition to the blank string and you also should check what happens with the end of the first word.
rem Char Number and words number
rem #echo off
cls
echo ===============================================================
set /P a=input string:
::set variables
set Temp_str=%a%
set /A charcounter = 0
set /A wordscounter = 0
:loop
if "%Temp_str%" NEQ "" (
set actual_char=%Temp_str:~0,1%
if "%actual_char%"==" " ( set /A wordscounter+=1 )
set Temp_str=%Temp_str:~1%
set /A charcounter+=1;
goto loop
)
REM Increment word count for the final word
if "%a%" NEQ "" ( set /A wordscounter+=1 )
echo %a% %charcounter% %wordscounter%

regular expressions batch

I'm writing a calculator on a cmd with enabled binary operations. I need to validate input data (remove letters, and other symbols that are not required for arithmetic operations)
#echo off
set data=
echo %* | findstr /R "\/\? ECHO" > nul
IF "%ERRORLEVEL%" EQU "0" goto printHelp
:main
set data= %data%%1
shift
if "%1" == "" (
echo %data% | findstr /R "^[0123456789*-+()/%!^_&|]*$" >nul 2>&1
if "%ERRORLEVEL%" EQU 0 (
echo Incorrect input data
exit /B
)
goto :result
) else (
goto :main
)
:result
set /a data="%data%"
echo %data%
exit /B
:printHelp
echo.
echo --------------------------------------------------
echo Using: calculator.bat [/?] [EXPRESSION]
echo helps you to consider arithmetic in Command Line
echo --------------------------------------------------
exit /B
My regular expression is not working. Also not considered to be a binary operation. What could be the problem?
Part 1 - Why your "regex is not working"
Your logic is wrong. FINDSTR sets ERRORLEVEL to 0 if there is a match, 1 if no match. Your regex is verifying that all characters are "valid", but your condition is treating a match as incorrect input.
Your IF statement uses quotes on one side, but not on the other. You must be consistent, otherwise it can never evaluate to TRUE.
Percent literals must be doubled within a batch script. Your regex has a percent literal that should be written as %%.
You use %ERRORLEVEL% in the same code block that sets the value. This cannot work because the value is expanded when the code block is parsed - before the value is set.
The simplest alternative is to use if errorlevel 1, which returns true if ERRORLEVEL is >= 1.
Another option is to enable delayed expansion with SETLOCAL ENABLEDELAYEDEXPANSION at top, and then use if !errorlevel! neq 0. But this would require that quoted ! literal in your regex be escaped as ^!, and ^ literal escaped as ^^.
My favorite option is to use the && and || conditional operators instead of IF.
findstr ... >nul && (match found statements) || (no match statements)
In your case, you want to take action if there was no match, so you only need the || operator.
Part 2 - Why your whole concept is not a good idea
Your validation is overly simplistic. Simply screening out invalid characters does not prevent errors. For example, 1**2 will result in an error, even though all characters are "valid". There are many other inputs with "valid" characters that would result in an error.
SET /A can work directly with environment variables. It knows how to access the value without you expanding the value in your code. This can be a powerful tool. A variable name used in a computation can include any character that is not an operator. So one can argue that there are no invalid characters for SET /A computations. Your exclusion of "invalid" characters prevents use of variables in computations.
Below is a simple batch calculator program I wrote some time ago. It is in an endless loop requesting input and displaying the result, until you enter a quit command. It supports all operators supported by SET /A.
It allows you to define and use variables in your expressions. The result of the most recent computation is always stored in a variable named #.
The calculator can display results as decimal, hexidecimal, or binary.
By default, it only displays the result of the last computation. It can be instructed to also display the value of all variables after each computation.
You can enter a command instead of a math computation. All commands begin with a \
\ Quit
\V Toggle variable listing ON or OFF
\D Decimal mode - results are displayed as decimal
\H Hex mode - results are displayed as hexidecimal
\B Binary mode - results are displayed as binary
\C X Clear variable X
\C * Clear all variables
\C X* Clear all variables that begin with X
Entering nothing will list all the currently defined variables.
Cleared variables are undefined. Note that an undefined variable has an implicit value of 0.
Here is the code:
#echo off
setlocal enableDelayedExpansion
for /f "delims==" %%v in ('set') do set %%v=
set __skip=#COMSPEC#PATHEXT#PROMPT#__mode#__str#__skip#__clr###__dispVars#
set __mode=Dec
set __dispVars=0
:top
echo:
set __str=
set /p "__str=%__mode%> "
if "!__str!"=="\" exit /b
if "!__str!"=="" call :dispVar # & call :dispVars & goto :top
if /i "!__str:~0,2!"=="\C" call :clearVars &goto :top
if /i "!__str!"=="\H" (set __mode=Hex) ^
else if /i "!__str!"=="\D" (set __mode=Dec) ^
else if /i "!__str!"=="\B" (set __mode=Bin) ^
else if /i "!__str!"=="\V" (set /a "__dispVars=^!__dispVars") ^
else set /a #=(!__str!)
call :dispVar #
if !__dispVars! gtr 0 call :dispVars
goto :top
:clearVars
for /f "delims=,; " %%v in ("!__str:~2!") do (
set __clr=%%v
if "!__clr:~-1!"=="*" (
set __clr=!__clr:~0,-1!
for /f "delims==" %%x in ('set !__clr!') do (
if "!__skip:#%%x#=!"=="!__skip!" set "%%x="
)
) else set "%%v="
)
call :dispVar #
call :dispVars
exit /b
:dispVars
setlocal
for /f "tokens=1,2 delims==" %%v in ('set') do if "!__skip:#%%v#=!"=="!__skip!" call :dispVar %%v
exit /b
:dispVar Var
setlocal
if !__mode!==Hex call :num2hex %1 disp
if !__mode!==Bin call :num2bin %1 disp
if !__mode!==Dec set /a disp=!%~1!
set var=%~1
if "!var:~0,6!"=="!var!" (
set "var=!var! ----------"
set "var=!var:~0,6!"
)
echo %var% = !disp!
exit /b
:num2hex NumVal RtnVar
setlocal enabledelayedexpansion
set hex=
set /a "dec=%~1"
set "map=0123456789ABCDEF"
for /l %%n in (1,1,8) do (
set /a "d=dec&15,dec>>=4"
for %%d in (!d!) do set "hex=!map:~%%d,1!!hex!"
)
(endlocal & rem return values
set %~2=%hex%
exit /b
)
exit /b
:num2bin NumVal RtnVar
setlocal enabledelayedexpansion
set bin=
set /a "dec=%~1"
for /l %%n in (1,1,32) do (
set /a "d=dec&1,dec>>=1"
set "bin=!d!!bin!"
)
(endlocal & rem return values
set %~2=%bin%
exit /b
)
exit /b
And here are the results of a short session:
D:\test>calculate.bat
Dec> 2*3
# ---- = 6
Dec> a=#+1
# ---- = 7
Dec>
# ---- = 7
a ---- = 7
Dec> b=(a+=5)*2
# ---- = 24
Dec> \v
# ---- = 24
a ---- = 12
b ---- = 24
Dec> c=b/3
# ---- = 8
a ---- = 12
b ---- = 24
c ---- = 8
Dec> \h
# ---- = 00000008
a ---- = 0000000C
b ---- = 00000018
c ---- = 00000008
Hex> \b
# ---- = 00000000000000000000000000001000
a ---- = 00000000000000000000000000001100
b ---- = 00000000000000000000000000011000
c ---- = 00000000000000000000000000001000
Bin> \
D:\test>

batch file: if %variable% (commands)

i want to use my %variable% to manage the conditional clauses in a IF.. THEN.. ELSE in a batch file.
Something like the following:
set variable=%%homedrive%% EQU C:
if %variable% (
echo test ok
) else (
echo test fail
)
if i write on a cmd console:
set test=1 equ 1
if %test% echo OK
it works!
i'll use it in a for /f cicle:
this is my pseudo codethis is my pseudo code to correct
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
[..]
) > "%temp%\CSG_fs.tmp"
[..]
for /f "usebackq tokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set cond=!cond:~1!
set parm=%%b& set parm=!parm:~0,-1!
echo - cicle: "!cond!" --^> "!parm!"
call if !cond! call:CSG_sub_fs !parm!
echo - done
)
goto:eof
:CSG_sub_fs
[..]
goto:eof
--edit--
how can i use the variable !cond! to decide if execute the call to CSG_sub_fs?
call if !cond! call:CSG_sub_fs !parm!
does not work because it returns: "Can not find the batch label specified - IF"
and if i use
if !cond! call:CSG_sub_fs !parm!
it will say: "call:CSG_sub_fs not expected"
Well - there doesn't seem to be a question, so it's not that easy to answer.
You have a problem with
echo "^%COMPUTERNAME^% EQU [x];[some parameters1]"
because ^ does not escape % - % escapes % - use %%COMPUTERNAME%%...
(you should have been able to check this just by TYPEing "%temp%\CSG_fs.tmp"
Next problem is that
for /f "tokens=1-2* delims=; usebackq" %%a in (%temp%\CSG_fs.tmp) do (
may process the file %temp%\CSG_fs.tmp provided %temp%\CSG_fs.tmp contains no spaces, semicolons or commas. If it contains any of these deafult separators, or certain other characters with a special meaning, then you must enclose the filename in double-quotes "%temp%\CSG_fs.tmp"and use the usebackq option.
You've attempted to use usebackq but DELIMS must be the LAST option if it is used. Your code would set ";","","u","s","e","b","a","c","k" and "q" as delimiters.
Beyond that, perhaps if you explain what you intend to achieve, we'd be able to devise the appropriate code.
Try this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CLS
REM I'm setting these variables for testing.
REM That isn't ususally a good idea but the SETLOCAL
REM will ensure they are restored on exit
SET computername=[x]
SET logonserver=[z]
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
) > "%temp%\CSG_fs.tmp"
for /f "usebackqtokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set "cond=IF !cond:~1! CALL :csg_sub_fs "
set parm=%%b& set parm=!parm:~0,-1!
CALL :varcmd "!cond!" "!parm!"
)
GOTO :eof
:varcmd
%~1 %~2
GOTO :eof
:csg_sub_fs
ECHO parameters supplied to csg_sub_fs were: %*
GOTO :eof
I've forced the variablenames to match the conditions you've used in order to trigger the subroutine calls. Change as you need to prove your concept.
And dont worry about imperfect English. I'm sure I wouldn't do as well in your language!

Batch File If statement inside For loop

I am having the issue where my if statement (inside a for loop), doesn't seem to cooperate. What I am trying to do is this:
Loop through a bunch of zip files and rename them 005.zip, 006.zip, 007.zip, etc.
I keep a counter, starting at 5, that determines the file number, and a prefix that is 00 in order to get 005, 006, and so on.
Once the counter reaches 10, I want the prefix to just be 0 instead of 00. So when the counter is ten, that file will be named 010.zip, and then 011.zip instead of 0010.zip, 0011.zip etc.
Here is what I have thus far:
setlocal enableextensions enabledelayedexpansion
SET /a COUNT=5
SET FILE_PREFIX=00
SET /a MAX=10
for %%f in (*.zip) do (
if !COUNT! == !MAX! (set FILE_PREFIX=0)
ren "%%f" %FILE_PREFIX%!COUNT!.zip
set /a COUNT+=1
echo !COUNT!
)
endlocal
Why doesn't the if statement work? The file renaming is working fine, it is just that if statement that doesn't change the FILE_PREFIX to 0.
The problem is that your code doesnt apply delayed expansion to the FILE_PREFIX so the value is calculated just once in the loop, at parse time; instead of being refreshed every iteration at runtime.
Just change your line to
ren "%%f" !FILE_PREFIX!!COUNT!.zip
and presto! it should work.
But once you correct it, still your method would fail for numbers above 999.
For a more robust implementation, try this alternative
SET /a count=1
for %%f in (*.zip) do (
set fn=0000!count!
echo REN "%%f" !fn:~-4!%%~xf
set /a count+=1
)
Inside the loop
the code 0000!count! appends some zeros (4 in this case) to the number; so it will follow the sequence 00001, 00002, ... 00009, 000010, 000011, ...
then !fn:~-4! removes all digits but the last N (4 in this example). So it will follow the desired sequence 0001, 0002, ... 0009, 0010, 0011, ...
and %%~xf extracts the extension (.zip in all the cases of this loop) and appends it to form the final filename. So it will follow the desired sequence 0001.zip, 0002.zip, ... 0009.zip, 0010.zip, 0011.zip, ...
This method will work for any number up to 9999. You can easily extend it to 5 o 6 or even more digits.

"Programming" a Batch file, IF statements inside IF statements?

Why won't this code work correctly?
I am sorry I couldn't understand how to post the code, so here is an image of the code:
![enter image description here][1] (also, please click the link because I am a new user and I can't post images yet)
Is Command Prompt even capable of executing this "branched IF commands" correctly?
If so, what am I doing wrong? Anyone knows? Please, reply!
:STARTEXITING
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_1.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_1.txt
if %error1eve1%==0 (
SLEEP 2
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_2.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_2.txt
if %error1eve1%==0 (
SLEEP 3
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_3.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_3.txt
if %error1eve1%==0 (
process -q uTorrent.exe 15
:STARTSTARTING
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_1.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_1.txt
if %error1eve1%==0 (
SLEEP 2
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_2.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_2.txt
if %error1eve1%==0 (
SLEEP 3
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_3.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_3.txt
if %error1eve1%==0 (
D:
cd\
cd Dropbox
cd uTorrent
start uTorrent.exe
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTEXITING
) else (
SLEEP 1
GOTO STARTEXITING
) else (
SLEEP 1
GOTO STARTEXITING
For great justice: This text was OCR-ed from http://i.stack.imgur.com/RgsId.png
cmd can handle nested ifs just fine. Your problem is a different one. As it stands all your if checks, except for the first will not do what you want.
Use delayed expansion by putting a
setlocal enabledelayedexpansion
at the top of your batch file and use !errorlevel! instead of %errorlevel%.
However, since you only check for Errorlevel being 0 you can just as well do
if not errorlevel 1 ...
instead of
if %errorlevel%==0
Joey has diagnosed one problem concerning delayed expansion. You have another - you should not put a label within an IF ELSE block - you most likely will not get your desired result. See https://stackoverflow.com/a/8481978/1012053.
Christian has a great suggestion to restructure your code to get rid of the nesting.
Since you are simply executing the same commands with increasing sleep intervals, you can use a FOR /L loop to further simplify your code.
#echo off
:startExiting
set started=
for /l %%N in (1 1 3) do (
if defined started sleep %%N
set started=1
"D:\dbStatusChecker\dbFileStatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_%%N.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_%%N.txt || goto :startExiting
)
process -q uTorrent.exe 15
:startStarting
set started=
for /l %%N in (1 1 3) do (
if defined started sleep %%N
set started=1
"D:\dbStatusChecker\dbFileStatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_%%N.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_%%N.txt || goto :startStarting
)
d:
cd \Dropbox\uTorrent
start uTorrent.exe
Since all the else clauses end with a goto, why not reverse them all, then you will eliminate the nesting.
If the code works, job done. If it still doesn't work, well that's one less factor to think about.