I wish to write a Windows Batch script that first tests to see if any of the command line arguments are equal to /?. If so, it displays the help message and terminates, otherwise it executes the rest of the script code. I have tried the following:
#echo off
FOR %%A IN (%*) DO (
IF "%%A" == "/?" (
ECHO This is the help message
GOTO:EOF
)
)
ECHO This is the rest of the script
This doesn't seem to work. If I change the script to:
#echo off
FOR %%A IN (%*) DO (
ECHO %%A
)
ECHO This is the rest of the script
and call it as testif.bat arg1 /? arg2 I get the following output:
arg1
arg2
This is the rest of the script
The FOR loop appears be ignoring the /? argument. Can anyone suggest an approach to this problem that works?
Something like this should do the trick:
#echo off
IF [%1]==[/?] GOTO :help
echo %* |find "/?" > nul
IF errorlevel 1 GOTO :main
:help
ECHO You need help my friend
GOTO :end
:main
ECHO Lets do some work
:end
Thanks to #jeb for pointing out the error if only /? arg provided
Do not use a FOR loop, but use the following instead:
#ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
IF "%1" == "/?" (
ECHO This is the help message
GOTO:EOF
)
SHIFT
GOTO Loop
:Continue
ECHO This is the rest of the script
:EOF
Related
I have a Script with different subroutines:
REM ---------------MAIN------------------------START----------------------------
call :SUB_GetStartTime
call :SUB_SettingVariables
call :SUB_CheckingParameters %*
call :SUB_Copy
call :SUB_GetEndTime
call :SUB_WriteLog
call :SUB_EndScreen
REM ---------------MAIN------------------------END------------------------------
At SUB_CheckingParameters I have this if query:
if "%~1"=="/help" (
GOTO SUB_HELP
)
If I pass the parameter /help it goes to my help window:
cls
ECHO ===================HELP==============
ECHO help text help text help text
ECHO =====================================
timeout /t 120
exit /b
after exit /b I want the script to end but it just goes to my next subroutine (SUB_Copy). Shouldnt the script end because I use GOTO SUB_Help and not call ?
Can someone help me and tell me what I am doing wrong?
I ususally handle this by passing back an errorlevel:
#Echo off
REM ---------------MAIN------------------------START----------------------------
call :SUB_GetStartTime
call :SUB_SettingVariables
call :SUB_CheckingParameters %* || Exit /b 1
call :SUB_Copy
call :SUB_GetEndTime
call :SUB_WriteLog
call :SUB_EndScreen
REM ---------------MAIN------------------------END------------------------------
Echo end of main
Pause
Goto :Eof
:SUB_CheckingParameters
if /I "%~1"=="/help" GOTO SUB_HELP
:SUB_GetStartTime
:SUB_SettingVariables
:SUB_Copy
:SUB_GetEndTime
:SUB_WriteLog
:SUB_EndScreen
Echo:We are in %~0 Args %*
Goto :Eof
:SUB_HELP
rem cls
ECHO ===================HELP==============
ECHO help text help text help text
ECHO =====================================
timeout /t 120
exit /b 1
(This is my first post here, so bear with me)
Can you show the last user-input in a batch file? I'm gonna try to keep it simple here.
#echo off
:menu
echo Type 1 to proceed.
set /p example=
if "%example%" == "1" GOTO :proceed
GOTO :error
:proceed
pause
:error
cls
echo You wrote (last user input), that's not correct.
timeout 30
GOTO :menu
I know that I could replace the (last user input) with %example%, but then I'd have to make custom error messages for every category, and there are about 50 of them. It'd be easier with a last input command.
By the way, I've taught myself everything that I know about batch, so my example probably has major issues right now, but it works somehow.
You could centralize all user input into a function (user_input)
:menu1
echo Type 1 to proceed.
call :userInput example
if "%example%" == "1" GOTO :proceed
GOTO :error
:menu2
echo Type 42 to proceed.
call :userInput answer
if "%answer%" == "42" GOTO :proceed
GOTO :error
:userInput
set /p LAST_INPUT=
set "%1=%LAST_INPUT%"
exit /b
:proceed
pause
:error
cls
echo You wrote "%LAST_INPUT%", that's not correct.
timeout 30
GOTO :menu
I don't know how to do it without temp file. TO get the things written int the console you need the doskey /history (this will skip the running of the script itself):
#echo off
setlocal enableDelayedExpansion
set "last="
set "but_last="
doskey /history > log.txt
for /f "tokens=* delims=" %%# in (log.txt) do (
set "but_last=!last!"
set "last=%%#"
)
echo "%but_last%"
del /s /q log.txt >nul 2>nul
I am trying to compare one variable from user input("yes")
, and predefined("yes") values. However, when I run the .bat file the cmd give me the syntax error message. Please help me how to compare two string values in if statement. thank you.
Here is Code:
#echo off
goto main
:main
setlocal
set ans=yes
set /p var=do you have problem?:
echo %var%
if "%var%" == "%ans%"(
echo there is problem
)
echo.
endlocal
goto :eof
Output:
The syntax of the command is incorrect.
Try this
#echo off
goto main
:main
setlocal
set ans=yes
set /p var=do you have problem?:
if "%var%" == "%ans%" (echo there is problem) else (echo there is no problem)
endlocal
goto :eof
Except I think this is cleaner:
#echo off
:main
set /p var=do you have problem?:
if "%var%" == "yes" (echo there is problem) else (echo there is no problem && goto :main)
PAUSE
A while ago I made a function that you can call from the command prompt or any batch file (it was just for fun, I don't see how it could be useful). It basically just makes your (Microsoft) computer speak whatever you wrote in as the parameter.
I recently got some inspiration to add a switch to it where it would read the contents of a file. My standalone script worked, but when I added it to my function, it didn't work as I would have liked.
Here's the code:
#echo off & setlocal enabledelayedexpansion
if "%~1"=="/?" (
echo.
echo TALK "Text" [Parameters]
echo.
echo Text - The phrase you want to be spoken.
echo.
echo [Parameters]:
echo /f - Read the contents of a file. "Text" changes to the file path.
echo.
endlocal
exit /b
)
if "%~2 X" equ "/f X" (
if not exist %~1 (
echo File does not exist or cannot be found.
endlocal
exit /b
)
set cont=
for /f "delims=" %%i in (%~1) do set cont=!cont! %%i
:b
echo Set a = Wscript.CreateObject("SAPI.SpVoice") > "Talk.vbs"
echo a.speak "%cont%" >> "Talk.vbs"
start /WAIT Talk.vbs
del Talk.vbs
endlocal
exit /b
)
set text=%~1
echo set speech = Wscript.CreateObject("SAPI.spVoice") > "talk.vbs"
echo speech.speak "%text%" >> "talk.vbs"
start /WAIT talk.vbs
del Talk.vbs
endlocal
exit /b
Unfortunately I don't have working function code (before I added the /f switch).
This is a last resort for me as I've edited it heavily and scoured the code for any give away as to what the problem might be.
Another bad thing is that I didn't take note of what I changed, so I can't exactly tell you what I've tried. I can tell you what the outputs are though.
The first time I tried, it gave the output The syntax of the command is incorrect.
It's now at the point where the original function (just converting text to speech) doesn't work anymore. The contents of the file Talk.vbs (which was made during the process) is a.speak "".
I'll keep updating my attempts, but knowing me it's something really simple that I've overlooked.
--EDIT--
At the suggestion of someone, I put carats before the square brackets in the syntax section. Nothing changed.
Along with escaping the parenthesis you also had to surround if exist %~1 in quotes in case of a argument of "some words I want it to say". Also cleaned it up a bit. Code at the bottom, but first an explanation.
If you looked at talk.vbs before it was deleted you would see this:
a.speak "!cont! contents of the file here"
This is because of this code:
for /f "delims=" %%i in (%~1) do set cont=!cont! %%i
:b
echo Set a = Wscript.CreateObject("SAPI.SpVoice") > "Talk.vbs"
If you turned echo on and watched the code you would see the last unescaped ) was taking the contents of the for loop and including it in the redirect.
Corrected and cleaned code:
#echo off & setlocal enabledelayedexpansion
if "%~1"=="/?" (
echo.
echo TALK "Text" [Parameters]
echo.
echo Text - The phrase you want to be spoken.
echo.
echo [Parameters]:
echo /f - Read the contents of a file. "Text" changes to the file path.
echo.
endlocal
exit /b
)
set text=
if [%2]==[/f] (
if exist "%~1" (
for /f "usebackq delims=" %%i in (%1) do set text=!text! %%i
) else (
endlocal
exit /B
)
)
if [%2]==[] set text=%~1
echo set speech = Wscript.CreateObject^("SAPI.spVoice"^) > "talk.vbs"
echo speech.speak "%text%" >> "talk.vbs"
cscript //NoLogo //B talk.vbs
del Talk.vbs
endlocal
exit /b
Edit: fixed the for statement pointed out by Andriy M
In your echo statements that contain parentheses, try escaping the parentheses with carats. I suspect especially the echo within the if statement is partially getting evaluated literally.
One other minor suggestion, I would also replace
start /WAIT Talk.vbs
with
cscript /nologo Talk.vbs
It's not that I think the start /wait is causing the error, but it does cause a second console window to appear temporarily for no good reason -- or it will whenever your script executes that far, anyway.
I made a few other suggested changes here, such as eliminating the need for a /f switch. If "%1" is the name of a file that exists, read it. Otherwise, treat it as text to read. And instead of having a separate subroutine for reading a file versus getting text from input, all that needs to happen is a variable has a different value.
#echo off & setlocal enabledelayedexpansion
if "%1"=="/?" ( goto usage )
if "%1"=="" ( goto usage )
if "%1"=="--help" ( goto usage )
if exist "%1" (
set txt=
for /f "usebackq tokens=*" %%i in (%1) do set txt=!txt! %%i
) else (
set txt=%1
)
echo Set a = Wscript.CreateObject^("SAPI.SpVoice"^) > "talk.vbs"
echo a.speak "%txt%" >> "talk.vbs"
cscript /nologo talk.vbs
del talk.vbs
endlocal
goto :EOF
:usage
echo.
echo TALK ["text"^|filename]
echo.
echo talk filename -- speaks the contents of filename
echo talk "text" -- speaks the supplied text
endlocal
goto :EOF
In a batch file I want to see if %1 is in a set.
E.g., as an alternative to
if %1 equ /? goto help
if /I %1 equ -? goto help
if /I %1 equ /help goto help
etc
It seems like it should be simple, but I can't make it work. I've tried with and without FOR loops and search:string.
#echo off
setlocal enabledelayedexpansion
set "helpoptions=#/?#-?#/help#"
if not "!helpoptions:#%~1#=!"=="%helpoptions%" goto help
goto :eof
:help
echo Help
would be an option, albeit not a very pretty one.