Errorlevel with choice in batch files executes wrong cases - if-statement

can someone tell me how can I make errorlevel stop taking value 1 or bigger? I want it to take into consideration only the exact value. If I choose 2, I want it to take the second option.
Right now if I choose '1', it executes the option for DLL file instead of LOG. I tried different versions like:
if errorlevel 1, tried using brackets with else etc. but none of them worked. Whats wrong with this code?
#echo off
cls
choice /C 12 /M "dll or log?"
if %errorlevel%=="2" dir %1\*.dll >> %2.txt
echo DLL
goto end
if %errorlevel%=="1" dir %1\*.log >> %3.txt
echo LOG
goto end
:end
exit /b

The ERRORLEVEL value is always numberic. The "compare ops" can be used. See IF /? for more infornation.
Quoting file system paths is needed in case there are SPACE or other special characters in the path. As mentioned by #Gerhard, using a TILDE in "%~3" removes any existing QUOTATION MARK characters around the %3 parameter.
BTW, this script does not check that %1, %2%, or %3 have any actual value or that the value it has is usable.
#echo off
cls
SETLOCAL ENABLEEXTENSIONS
choice /C 12 /M "dll or log?"
if %errorlevel% EQU 2 (
dir "%~1\*.dll" >> "%~2.txt"
echo DLL
goto end
)
if %errorlevel% EQU 1 (
dir "%~1\*.log" >> "%~3.txt"
echo LOG
goto end
)
:end
exit /b

this resolve:
#echo off
cls
rem choice /C 12 /M "dll or log?"
choice /C 12 /M "log or dll?"
if %errorlevel%==2 (dir %1\*.dll >> %2.txt
echo DLL
goto end)
if %errorlevel%==1 (dir %1\*.log >> %3.txt
echo LOG
goto end)
:end
exit /b
you need control the flow whith "(" ")" and the " around the errorlevel number is not necessary.
BONUS
This an alternative method that is more flexible:
#echo off
if "%~3"=="" echo lack of parameters & goto :EOF
cls
choice /C 12 /M "log or dll?"
Goto Choice%ErrorLevel%
:Choice2
dir "%~1\*.dll" >> "%~2.txt"
echo DLL in %~1
goto end
:Choice1
dir "%~1\*.log" >> "%~3.txt"
echo LOG in %~1
goto end
:end
exit /b
The ~ in the parameters remove eventual sorround double quote. Then the surrond quoted added can prevent parameters with space inside.

Related

All letters, numbers and symbols in one?

Hey does anyone know if there is a command or something that allows me to have all the letters, numbers and characters in one?
:start
set input=
set /p input=[Y / N]?
if %input%==Y goto y
if %input%==N goto n
if %input%==* goto this
:y
goto end
:n
exit
:this
#echo. Only J or N
:end
Here you can already see that I tried to get everything in one with "*" which unfortunately didn't work...
Thank you for trying to help me but I would like to point out again that I need help to find something that allows me to use all the characters, letters and symbols in one.
example:
if I take y then he goes on.
if I take n then it closes. and when i use g or h he says: "can't do,
just y and n (for yes and no)"
but things like "*" or "%word%" don't work and yes, I have "choice /?" Already tried but when I do it like this it doesn't work either:
for %%i in (
D o " you " k n o w " to " h e l p " me
) do (<nul set /p "=.%bs%%%~i" & >nul ping -n 1 localhost)
# echo ?
CHOICE
[I don't care about syntax errors or something. if it works then it fits, it's just this one thing to use all characters, letters and symbols in one.]
No hate <3
if has no wildcard, but as I already commented, you don't need the third if at all. If Y and N are already handled, it can only be "anything else"
:start
set "input="
set /p "input=[Y / N]? "
if "%input%"=="Y" goto y
if "%input%"=="N" goto n
echo it's Y or N, nothing else&goto :start
The quotes makes it a little bit safer, but note this still isn't safe at all.
Cmd handles several characters (so called "poison chars" like <>|&"!) different (and even more under certain conditions).
A more secure method:
#echo off
setlocal enabledelayedexpansion
:loop
set "input="
set /p "input="
>nul 2>&1 (
echo/!input!|findstr /x "Y" >nul && goto YES
echo/!input!|findstr /x "N" >nul && goto NO
)
echo FAIL
goto :loop
:YES
echo yeah
goto :eof
:NO
echo nope
goto :eof
(Disclaimer: I'm quite sure, someone will find an input-string to make it fail too)
Note: both if and findstr support the /i switch to make them case-insensitive.
And just for the sake of showing everyone else how to perform this task using the appropriate commands:
%SystemRoot%\System32\choice.exe
If ErrorLevel 2 Exit /B
Rem The code you had under :end replaces this line

Alternative to grep for isolating specific text in Windows command line

My network changes rather dynamically and unfortunately I am forced to run Windows.
This script works because I have installed GNU tools for Windows and can use grep.
I would like to be able to run this script on any windows machine without having to install anything (grep etc). I used findstr in this at first but could not get it to show only what matches the regex string.
#echo off
set %IPLIST% = nul
Echo.
Echo "Pinging all local Gateways"
ipconfig | findstr /i "Gateway" | grep -o "[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*" > %IPLIST%
For /F "Usebackq Delims=" %%# in ("%IPLIST%")
do (
Echo+
Echo [+] Pinging: %%#
Ping -n 1 "%%#" 1>nul && (
Echo [OK]) || (
Echo [FAILED])
)
Echo.
Echo.
Echo "now testing your internet connection"
Echo .
Echo ...
if %errorlevel% == 0 (
echo ....you're all good bro.
) else (
ping -n 3 "8.8.8.8" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 1 (
echo ....all is lost
)
)
Echo.
You have a number of problems with the script.
set %IPLIST% = nul
This would yield a syntax error because iplist is likely undefined, and you are attempting to set the variable contents of iplist to "nul"
The resolution of this would be
set = nul
Further, spaces on either side of the = are included in the variable/value set, so removing the %s would set the value of iplistSpace to Spacenul
Had iplist indeed been set up to nul then your ipconfig command would have simply dumped its eventual output into the bit-bucket as it would have been sent to nul.
For /F "Usebackq Delims=" %%# in ("%IPLIST%")
The do ( must be on the same physical line as the "for"
<opinion>Using non-alphas as metavariables is not a good idea as it is not officially supported <\opinion>
if %errorlevel% == 0 (
echo ....you're all good bro.
) else (
ping -n 3 "8.8.8.8" | findstr /r /c:"[0-9] *ms"
if %errorlevel% == 1 (
echo ....all is lost
)
)
Because of the delayed expansion trap (all %var% in a block (parenthesised sequence of statements) are replaced by their value at parse-time) the innermost %errorlevel% here would be replaced by whatever errorlevel was set to when the outermost if was encountered. To interpret the ping output, you'd need to either invoke delayedexpansion (many, many SO items on this subject) or use the old original if errorlevel n... construct, where the if condition is true if the current errorlevel is n or greater than n.
So - reconstructing using batch features,
#ECHO OFF
SETLOCAL
Echo.
Echo "Pinging all local Gateways"
For /F "tokens=2 Delims=:" %%a in ('ipconfig ^| findstr /i "Gateway"') DO IF "%%a" neq " " (
Echo+
Echo [+] Pinging: %%a
Ping -n 1 %%a 1>nul && (
Echo [OK]) || (
Echo [FAILED])
)
Echo.
Echo.
Echo "now testing your internet connection"
Echo .
Echo ...
if %errorlevel% == 0 (
echo ....you're all good bro.
) else (
ping -n 3 "8.8.8.8" | findstr /r /c:"[0-9] *ms"
if ERRORLEVEL 1 IF NOT ERRORLEVEL 2 (
echo ....all is lost
)
)
Echo.
GOTO :EOF
The 'for /ftokenises the output of the command in single-quotes using:as a delimiter and picking the second token to apply to%%a`.
The | needs to be escaped by a caret to tell cmd that it is part of the command to be executed, not part of the for.
The for processes the output of ipconfig... so %%a has the form Spacexxx.xxx.xxx.xxx
On my machine, xxx... was missing on one line, so I filtered out the single-space response.
Pinging %%a without the quotes adds an extra space into the ping line, which is harmless. With the quotes, it didn't like it.
Then the appendix...
I'm not sure what you're really attempting here. Perhaps it was a frustrated debug attempt.
errorlevel will be set to whatever the last ping result was. This is logically unpredictable.
I've shown a correct method of interpreting the findstr errorlevel result. I'm not sure that your regex is correct here...but the all is lost message would only be shown if findstr sets errorlevel to 1.

CMD IF statements

I want to check whether or not variable h="yes" or h="no" and my code is obviously incorrect. how could i fix it?
#echo what is your statement (YES/NO)?
set /p h=
if %h% EQ 'yes' goto YES
if %h% EQ 'no' goto NO
:YES
#echo you chose YES
pause > nul
goto END
:NO
#echo you chose NO
pause > nul
:END
just a little chages are neccessary:
#echo off
echo what is your statement (YES/NO)?
set /p h=
if /i '%h%' == 'yes' goto YES
if /i '%h%' == 'no' goto NO
echo wrong input
goto END
:YES
echo you chose YES
pause > nul
goto END
:NO
echo you chose NO
pause > nul
:END
the correct syntax for "is equal to" is: EQU or ==
if /i makes it case-insensitive, so you can enter yes, YES, Yes or yEs
I added two lines for wrong input
I have been asked to whittle my response down.
I think this what you are looking for which is something like:
#ECHO OFF
CLS
CHOICE /C YN /M "DO YOU WANT TO RESTART APACHE TOMCAT WEB SERVICE?"
IF %ERRORLEVEL% == 2 GOTO END
ECHO DO OTHER STUFF HERE
:END
ECHO YOU PRESSED N OR SCRIPT HAS FINISHED
EXIT

bat: Listing empty directories, if/else statements within for statements?

I'm trying to write a script that lists every file name in a specified folder, and notifies the user if that folder is empty. So far I've got:
for /r "O:\Mail\5-Friday" %%d in (*.pdf) do (
dir /a /b "%%~fd" 2>nul | findstr "^" >nul && echo %%~nd || echo Empty: Friday
)
but I've no idea where to put the if, else operators.
And is there a way to specify a folder based on user input without rewriting every function for each folder? So instead of:
if /i {%ANS%}=={thursday} (goto :thursday)
if /i {%ANS%}=={friday} (goto :friday)
:thursday
<do stuff>
:friday
<do the same stuff as thursday, but a different directory>
etc, I could write one function with variables in place of paths, assign the directory to a variable, and easily add/remove folders in the code as necessary?
To address the first part of your question, "where to put the if, else operators"... The notation of
command | findstr >nul && echo success || echo fail
... is shorthand for
command | findstr >nul
if ERRORLEVEL 1 (
echo fail
) else (
echo success
)
The magic that happens is in the conditional execution operators, the && and ||. If findstr exits with status zero, then a match was found. Therefore, execute the stuff after &&. Otherwise, status is non-zero, no match was found, so execute the stuff after ||. See how that works?
For the second part, here's a typical way to prompt the user to provide entry based on a finite number of choices.
#echo off
setlocal
:begin
set /p "day=What day? "
for %%I in (monday tuesday wednesday thursday friday) do (
if /i "%day%" equ "%%I" goto %%I
)
goto begin
:monday
call :getdirs "O:\Mail\1-Monday"
goto :EOF
:tuesday
call :getdirs "O:\Mail\2-Tuesday"
goto :EOF
:wednesday
call :getdirs "O:\Mail\3-Wednesday"
goto :EOF
:thursday
call :getdirs "O:\Mail\4-Thursday"
goto :EOF
:friday
call :getdirs "O:\Mail\5-Friday"
goto :EOF
:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
dir /b "%%I" 2>NUL | findstr "^" >NUL || echo %%I has no files
)
goto :EOF
Or, even hacksier, I'll do something you probably weren't expecting was possible. I'll have the script open a folder selection dialog to allow the user to select the directory to scan. It's a batch / JScript hybrid script.
If you wish, you can set the root of the folder browser to a ShellSpecialConstants folder by changing the last argument in the next-to-the-last line. Using a value of 0x11 makes the root your system's drives. No value or a value of 0x00 makes the root "Desktop". Or leave the script as-is to set the root as "O:\Mail".
#if (#a==#b) #end /*
:: fchooser2.bat
:: batch portion
#echo off
setlocal
set initialDir="O:\Mail"
for /f "delims=" %%I in ('cscript /nologo /e:jscript "%~f0" "%initialDir%"') do (
call :getdirs "%%I"
)
exit /b
:getdirs <path>
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('dir /b /s /ad "%~1"') do (
dir /b "%%I" 2>NUL | findstr "^" >NUL || (
rem This is where you put code to handle empty directories.
echo %%I has no files
)
)
goto :EOF
:: JScript portion */
var shl = new ActiveXObject("Shell.Application");
var hint = 'Double-click a folder to expand, and\nchoose a folder to scan for empty directories';
var folder = shl.BrowseForFolder(0, hint, 0, WSH.Arguments(0));
WSH.Echo(folder ? folder.self.path : '');
Edit Since apparently BrowseForFolder accepts an absolute directory, there's really no benefit to using PowerShell / C#. The hybrid batch / PowerShell / C# script shall henceforth be retired to the revision history.
This is fun!

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!