How to exit a user input loop in batch? - batch-file

Well I have a simple for loop to take user input and creat a file with this input, then ask for the next input and create "file2" etc., but I can't seem to figure out how my user can quit the loop with a certain input (maybe "exit" or "end").
setlocal enabledelayedexpansion
set x=1
:runName
set /p names="Enter header for file !x!:"
for %%a in (%names%) do (>>file!x!.txt (echo %%~a) set /a x+=1)
if !names!=end goto:eof else goto:runName
:eof
echo press any key to close
pause>nul
Ps. Sorry for the poor formatting, I cant figure how to enter my code in the grey field from my phone and dont have a computer at the moment.

I'm not quite shure why the input prompt says header.
Here is my best guess what you may have meant:
#Echo off
setlocal enabledelayedexpansion
set x=1
:runName
Set "names="
set /p names="Enter header for file%x%:"
if not defined names goto :end
if /I "%names%" Equ "end" goto :end
(
for %%a in (%names%) do (echo:%%~a)
) >file!x!.txt
set /a x+=1
goto :runName
:end
echo press any key to close
pause>nul
Running
Enter header for file1:anton bertha caesar
Enter header for file2:anchorage berlin
Enter header for file3:END
press any key to close
File content
> type file*.txt
file1.txt
anton
bertha
caesar
file2.txt
anchorage
berlin

I can't seem to figure out how my user can quit the loop
If you'll allow a suggestion, mine would be don't do that.
Almost any batch script is best written to accept command-line options and files as input. Once you trap the user into providing input interactively -- anything more than Y or N, and even that's a nuisance -- you're putting him in a bad spot. He can't re-run your script without going through the tedium again. He can't use tab completion, or pick from a list. He's trapped in a user-interface element that hasn't been improved in 30 years, and wasn't very good then.
I don't know what to suggest specifically. The example you provide is so trivial it would be easier to provide the file directly using Notepad than to create it with a script. Then you might want a verification script to make sure the provided input file is valid.

SETLOCAL ENABLEEXTENSIONS ENABLEDELAYEDEXPANSION
for /f "SKIP=0 EOL=; TOKENS=* DELIMS=" %%i in ('dir /b c:\windows\*.* ^|FIND /i *.exe') do (
CHOICE /D N /T 5 /C YN /M "Please pre Y to exit"
IF !ERRORLEVEL!==1 GOTO :END
IF !ERRORLEVEL!==2 ECHO CONTINUE
timeout 5
#echo %%i
)
:END
ENDLOCAL

Related

How to make a bat file that asks the user for the drive they want to fix?

I have always tried to do this but have resorted to entering this in the command line:
CHKDSK C: /f
I tried to look up how to do it but im not that big on bat file programming and more so am just a small programmer learning java atm...
I wanted to know how to do this and more so know how to compute it. As it would help me in the long term and also help me in the short term.
Would be much appreciated. :)
Using 'choice /c' command
This script will ask the user which drive to fix, and then show a confirmation message before 'fixing' the drive:
#echo off
:start
setlocal EnableDelayedExpansion
set letters= abcdefghijklmnopqrstuvwxyz
choice /n /c %letters% /m "Please enter the drive letter you would like to fix: "
set drv=!letters:~%errorlevel%,1!
echo Are you sure... to fix %drv%:\?
choice
if errorlevel 2 goto :start
chkdsk %drv%: /f
echo Complete!
pause
Using 'set /p' command
This script is easier to write and understand, but it shouldn't be used:
#echo off
:start
:: Clears the contents of the %drv% variable, if it's already set
set "drv="
:: Queries the user for input
set /p "drv=Please enter the drive letter you would like to fix: "
:: Check if input was blank
if "%drv%"=="" echo Don't leave this blank&goto :start
:: Check if input contained more then 1 letter (Doesn't account for numbers or special characters)
if not "%drv:~1,1%"=="" echo Please enter the drive letter&goto :start
echo Are you sure you want to fix %drv%:\?
choice
if errorlevel 2 goto :start
chkdsk %drv%: /f
echo Complete!
pause

How do I save variables from a batch file then load them to use them?

I'm a pretty inexperienced coder and I love batch because its one of the more straight forward coding languages but I want to save multiple variables to a txt file or other format then "load" those same variables to the batch file not to type so the player can see but so that I can use it
This is what I have so far for loading:
:nick
cls
color 02
set /p nick= Enter your nickname:
if exist ((savegame%nick%.txt) goto load)
goto instructions
:load
for /f "blevel=" %%a in (savegame%nick%.txt) do set blevel=%%a&goto loadexist
for /f "mlevel=" %%a in (savegame%nick%.txt) do set mlevel=%%a&goto loadexist
for /f "alevel=" %%a in (savegame%nick%.txt) do set alevel=%%a&goto loadexist
this is what I have for saving:
:save
cls
echo Saving please wait...
(echo blevel=%blevel%)> savegame%nick%.txt
(echo mlevel=%mlevel%)>> savegame%nick%.txt
(echo alevel=%alevel%)>> savegame%nick%.txt
timeout /t 5 /nobreak >nul
exit
Like I said I'm very inexperienced and my goal is to create a game please feel free to point out any flaws. In my game I have 3 characters Brutus, Mediana, and Achilles. blevel, mlevel, and alevel refers to the place in the game where you are and the character you chose to play as so you don't have to play the whole game to get to where you were.
As this is obviously still a work in progress I only have one instance where you can save and its in the first Brutus promt:
:brutus 1
set blevel=1
cls
echo.
echo.
echo.
echo You chose brutus good choice but are you sure this is who you want?
echo 1) go back and choose
echo 2) continue
echo 0) save
set /p c=C:\
if "%c%" == 1 goto choose character
if "%c%" == 2 goto brutus 2
if "%c%" == 0 goto save
goto brutus 1
So when you get to a choice like this your respective level goes up. Every time I reopen the game it either closes cmd when I type the nickname I used to save the file or it doesn't work and skips over it like the file or the variables in it don't exist. My intention is to do this with all three characters at every crucial choice so in the end I will probably have at least 100 per character.
your "save" logic is ok.
For loading, you need just a single line:
for /f "delims=" %%i in (savegame%nick%.txt) do set "%%i"
When you run it with echo on, you see that it processes every line and sets your variables.

BATCH program crashes after goto command

This code is part of a chat program that I am currently working on. The 'else' part of my program is the one that doesn't work. The program quits instead of going to :home
:join
cls
if not exist "C:/Users/Public/room.cmd" (
echo No room has been found.
echo.
set /p choiceretry=Do you want to retry? y/n
if "%choiceretry%"=="y" goto join
if "%choiceretry%"=="n" goto home
) else (
cls
"C:/Users/Public/room.cmd"
echo A room has been found.
pause >nul
echo Joining
set roomjoined=1
echo %roomjoined%
goto home
)
:home
echo this finally works
pause
I have tried changing the code several times starting from 'echo Joining'
Anyone know why cmd quits?...
:) :) :)
Thanks in advance
The problem is the way you run room.cmd; you must use call to return from it:
call "C:/Users/Public/room.cmd"
Otherwise, execution will not return from room.cmd to the original batch file that ran it.
Hint: Consider to use choice instead of set /P for Y/N decisions.
Firstly, please don't left justify your code blocks. It's much easier to read code that's properly indented.
Secondly, when retrieving values within a code block, you need delayed expansion. See setlocal /? in a cmd prompt for more information. This is the reason for the unexpected behavior. Your variables retrieved within the same parenthetical code block in which they were set won't contain the values you expect unless you retrieve them with delayed expansion syntax. As an alternative, you could use the choice command and if errorlevel, which would result in a bit nicer user experience I think.
Thirdly, when testing user input, you should use the /i switch in your if statements for case-insensitivity. This isn't relevant if using choice / if errorlevel though.
Fourthly, Windows paths use backslashes, not forward slashes.
I'd fix it this way:
#echo off
setlocal
:join
cls
if errorlevel 1 set /P "=Retrying... "<NUL
if not exist "C:\Users\Public\room.cmd" (
echo No room has been found.
echo.
choice /c yn /n /m "Do you want to retry? [y/n] "
if errorlevel 2 goto home
goto join
) else (
"C:\Users\Public\room.cmd"
echo A room has been found.
pause >nul
echo Joining
set roomjoined=1
)
:home
echo this finally works
pause

Batch Making Passwords

I have made a batch game where users can log in / register. But there is no point in having passwords if a person standing nearby can peep at the password. Normal password fields mask the characters with asterisks (*).
How can mask characters on a batch file?
I've seen this done on cmd before but I have no clue how.
You can use XCOPY for a hidden input, it can handle nearly all characters and you can also implement a backspace logic.
#echo off
setlocal EnableDelayedExpansion
call :input
echo(
echo '!input!'
if "!input!"=="password" echo OK
exit /b
:input
for /F "tokens=1 delims=# " %%a in ('"prompt #$H# & echo on & for %%b in (1) do rem"') do (
set "\b=%%a"
)
set "input="
:keyLoop
call :GetKey
if not defined key exit /b
if "!key!"=="!\b!" (
if defined input (
set "input=!input:~0,-1!"
<nul set /p ".=!\b! !\b!"
)
) ELSE (
<nul set /p ".=*"
set "input=!input!!key!"
)
goto :keyLoop
:GetKey
setlocal DisableDelayedExpansion
set "key="
for /F "usebackq delims=" %%L in (`xcopy /L /w "%~f0" "%~f0" 2^>NUL`) do (
if not defined key set "key=%%L"
)
(
endlocal
set "key=^%key:~-1%" !
exit /b
)
This code should be able to handle all characters, like ^!&%<>.
It's also possible to use backspace to delete the last entered character.
The line set "key=^%key:~-1%" ! seems odd, but it's used to escape the ! character with set "key=^!" ! in the delayed expansion context.
And to avoid problems for all other characters the last ! removes the caret, like in set "key=^A" ! will be evaluated to ``set "key=A"`
Ok, this is a bit different to what you may have had in mind, but that's you're fault for choosing batch for game dev.
The way I see it is you have 3 options:
Use an external program you self made in C#, C++, Python, [etc.]
Howver this requires an application to already do this for you (Which there probably is) or for you to have a knowledge in one of these languages
Use the choice command, to continuously take one key input and wait for the user to hit space to signify the end of the password
However this limits the password characters choice, and makes the program look ugly
Use 2 Batch threads, one that masks and tallies input while the other stores it to a variable.
This may be a bit dodgey at times, at would be a bit complicated but may be the only choice you have.
Now, as I was typing this an idea stuck my head on how to achieve this. Since it might take some time to test I thought I'd post the idea (as it seems to be a soloution to this problem, which has been around for a while).
Logic
One Batch Thread will simply use set /p to store all the input into a variable and upon completion will communicate to the other batch thread through the use of waitfor or a simple directory file.
Another Batch Thread would loop the pause >nul statement and would tally the number of times the pause statement is looped, printing out the appropriate amount of *'s. The other important job of this thread is to sense when the user has finished typing the password, upon which it exits.
Im starting to make this batch program now, but for now I'll just keep you informed of my idea so far.
Code
Login.bat
#echo off
Title Password Please:
:: This is the main code
REM This code relies on Masker.bat
REM SET password to be first and thrid letter,
REM of the day of the week.
set pass=%Date:~0,1%%Date:~2,1%
REM START Masker in the same window using /b tag and create hold.pass:
Echo 0 >%temp%\hold.pass
start /b Masker.bat "%pass%" *
REM Simply take input an leave the rest to Masker.bat
set /p pass_input=:
Echo 1 >>%temp%\hold.pass
cls
if /i "%pass%" NEQ "%pass_input%" (
Title Worng Password
Echo Wrong Password... Sorry.
Sleep 5
Exit
)
Pause > nul
REM Rest of Main game code is below or simply
:: START Main.bat & Exit
Masker.bat
#echo off
Title Password Please:
setlocal enabledelayedexpansion
:: This is not the main code
REM This code is called upon by Login.bat (or the Main.bat game code)
REM CREATE the variables "passlen" and "mask":
set password=%~1
set passlen=0
:miniloop
set /a passlen+=1
if "!password:~%passlen%,1!" NEQ "" goto :miniloop
set password=
set mask=%~2
if "%mask%" EQU "" set mask=*
REM MAIN loop
:loop
cls
for /l %%a in (1,1,%passlen%) do (<nul set /p=%mask%)
sleep -m 150
for /f "usebackq" %%a in ("%temp%\hold.pass") do (if "%%~a" EQU "1" Del %temp%\hold.pass & Exit)
goto :loop
It still needs some more improvements, but I've spent aroung 30 min on it with little success to make it dynamically tell you how many characters you have typed in.
Anyone cane take this up, be my guest. Everything else works fine
Mona
This works without pressing enter after input of the password.
If you enter the correct password, ok.
if you enter a wrong password, it will stop when you enter the 9th character (can be adapted).
It does not care about capitalization.
Problem: the password is stored as pure text in the code
#echo off
setlocal enabledelayedexpansion
set "s= abcdefghijklmnopqrstuvwxyz"
set p=
:loop
choice /C %s% /N >nul
set p=%p%!s:~%errorlevel%,1!&set /p =*<nul
if /i "%p%"=="secured" goto :right
if not "%p:~8,1%"=="" goto :wrong
goto :loop
goto :wrong
:right
echo you entered correct password: %p%
goto :eof
:wrong
echo you entered wrong password: %p%
goto :eof
You may use ReadFormattedLine subroutine for all kind of formatted input. For example, the command below read a password of 8 characters, display asterisks in the screen, and continue automatically with no need to press Enter:
call :ReadFormattedLine password="********" /M "Enter password (8 chars): "
This subroutine is written in pure Batch so it does not require any additional program, and it allows several formatted input operations, like read just numbers, convert letters to uppercase, etc. You may download ReadFormattedLine subroutine from Read a line with specific format.

How to find keywords of the users input in the command line?

What I'm looking for is a batch file line of code that will scan what the user inputs to find key words and direct them in the right place. That way when a trainee has a question he/she could just ask the batch file and it will direct them to the proper menu. Is this possible? if so, How would one go about doing this?
:menu
set /p c=Please type you question:
findstr /m "How to ringout a product on our system?" "%c%"
if %c%=="ringout" (
goto :Ringingout
) Else (
goto :Sorry
)
:Ringingout
cls
echo In order to right something out maksure you do the following:
echo - Log in
echo - click on scan in the bottom left had corner on the tender page
echo - scan items
echo - click continue
Pause
goto :Menu
:Sorry
cls
echo Sorry I don't recognize your question, please re-word it.
pause
goto :Menu
#ECHO OFF
SETLOCAL
SET "keywords=word anotherword someword"
FOR %%k IN (%keywords%) DO set "#%%k="
SET /p query="Please enter your query ? "
FOR %%k IN (%keywords%) DO CALL :analyse %%k
SET #
GOTO :EOF
:analyse
CALL SET "found=%%query:%1=%%"
IF "%found%"=="%query%" GOTO :EOF
SET #%1=FOUND!
GOTO :eof
Here's a general way to do it.
If one of the keywords is entered, the variable #keyword will be set to FOUND! so you can use if defined #keyword to process from there.
It's not protected against destructive user-inputs - that's not what this question is about...
You'd be better off collecting all the questions in a document (like .html) and letting the user search that document for what they need. But if this is just an exercise, you can re-write your logic like so to make your program work:
:menu
set "c="
set /p "c=Please type your question: "
echo %c% | findstr /i /b "ringout" >nul
if errorlevel 1 goto Sorry else goto Ringingout
:Ringingout
and so on.

Resources