Why this just closes the cmd after tipping the id? - batch-rename

#echo off
echo Type song ID:
set /p id=
for /r %userprofile%/AppData/Local/GeometryDash %%a in (*) do if "%%~nxa"=="%id%.mp3"
set p=%%~dpnxa
if defined p (
echo Type NoNG song path:
set /p nong=
echo Type NoNG file name (with .mp3):
set /p songname=
cd %nong%
ren %songname% %id%.mp3
::write move command here (just ignore)
pause
) else (
echo Song not found
pause
)
after tipping the id variable cmd just closes i tried to add pauses, exits everyware but nothing works i can't figure out what is happening.

If you can't find anything with pause, it must be directly on the 3rd line. As far as I understand it, you want to match the name and only continue when the name is found. I would recommend you this program line:
for /r %path% %%i in (%id%) do (
...
)
after that you can continue to work directly in the brackets with your variable

Related

Batch RPG Game with Login Function

I'm creating a D&D style RPG game using batch files and I saw another person using a login feature that creates a batch file that returns you to where you left off. so I tried to replicate it. Almost everything works except for the fact that it won't create the batch file to allow you to go back. When you go through the process of creating a login it goes through it like normal and on the next screen under start even displays that your username is what you set it as but it won't create the batch file. Some of the code might be scattered because I'm still learning and some of it unfinished but this is what I have so far.
title Lost Mine of Phandelvor
#echo off
:entergame
cls
echo.
echo Welcome to Lost Mine of Phandelvor
echo -------------------
echo.
echo 1. Create Account
echo 2. Login
echo 3. Exit
echo.
set /p input=
if %input% EQU 1 goto createuser
if %input% EQU 2 goto login
if %input% EQU 3 exit
if %input% GEQ 4 goto entergame
:createuser
cls
echo.
echo What would you like your Username to be?
set /p username1=
set v1f=0
goto checkforspaces
:checkforspaces
set x=!v1f!
set Letter%v1f%=!username1:~%x%,1!
if "!Letter%v1f%!" EQU " " (
echo.
echo.
echo Sorry you can't use spaces in your Username.
pause>nul
goto entergame
)
if NOT "!Letter%v1f%!" EQU "" (
set /a v1f=%v1f%+1
)
echo.
echo What would you like your Password to be?
set /p password1=
goto DATA_VALUES
:login
cls
set /p name=Username:
if not exist "%name%.bat" (
echo That is not a valid Username.
pause>nul
goto entergame
)
set /p pass1=Password:
call %name1%.bat
if not %password1% EQU %pass1% (
echo That is not a valid Password.
pause>nul
goto entergame
)
goto create
:DATA_FILES
set lvl1=1
set exp1=0
set expmax1=300
set gp1=10
set hp1=12
set ac1=15
set profbonus1=2
set str1=4
set dex1=1
set con1=2
set int1=0
set wis1=2
set cha1=2
set destination=SAVE_GAME_FILES
set destination2=SAVE_GAME_FILES
goto SAVE_GAME_FILES
:SAVE_GAME_FILES
(
echo set username1=%username1%
echo set password1=%password1%
:DATA_VALUES
echo set lvl1=%lvl1%
echo set exp1=%exp1%
echo set expmax1=%expmax1%
echo set gp1=%gp1%
echo set hp1=%hp1%
echo set ac1=%ac1%
echo set profbonus1=%profbonus1%
echo set str1=%str1%
echo set dex1=%dex1%
echo set con1=%con1%
echo set int1=%int1%
echo set wis1=%wis1%
echo set cha1=%cha1%
echo set destination=%destination%
echo set destination2=%destination2%
)>%username1%.bat
goto start
:start
cls
echo.
echo Currently logged in as %username1%
echo.
echo Welcome to my fantasy style role playing game.
echo You will need to create a character.
echo.
echo Enjoy!
echo.
echo 1. Continue to Character Selection
echo 2. Exit
echo.
set /p input=
if %input% EQU 1 goto create
if %input% EQU 2 exit
if %input% GEQ 3 goto start
:create
cls
echo.
echo Welcome to Character Creation
echo.
echo Pick your race!
echo.
echo 1. Human
echo 2. Dwarf
echo 3. Elf
echo 4. Dragonborn
echo 5. Tiefling
echo.
set /p input=Choice:
if %input%==1 goto createHuman
if %input%==2 goto createDwarf
if %input%==3 goto createElf
if %input%==4 goto createDragonborn
if %input%==5 goto createTiefling
goto create
:createHuman
cls
echo.
echo You have chosen Human as your race!
echo.
echo Choose your class
echo.
echo 1. Fighter
echo 2. Ranger
echo 3. Rogue
echo 4. Wizard
echo.
set /p input=Choise
if %input%==1 goto humanFighter
if %input%==2 goto humanRanger
if %input%==3 goto humanRogue
if %input%==4 goto humanWizard
goto createHuman
:humanFighter
cls
echo.
echo You have chosen Fighter as your class!
echo.
echo Choose your weapon
echo.
echo 1. Battleaxe 1D8 Slashing
echo 2. Longsword 1D8 Slashing
echo 3. Rapier 1D8 Piercing
echo.
set /p input=choise
if %input%==1 goto humanFighter1
if %input%==2 goto humanFighter2
if %input%==3 goto humanFighter3
goto humanFighter
:humanfighter1
set lvl1=1
set exp1=0
set expmax1=300
set gp1=10
set hp1=12
set ac1=15
set profbonus1=2
set str1=4
set dex1=1
set con1=2
set int1=0
set wis1=2
set cha1=2
cls
echo.
echo To find your stats open your character sheet labeled humanfighter1_cs.txt
echo.
echo What's your name?
echo.
set /p name1=Enter:
goto hf1main
:hf1main
cls
echo.
echo %name1% Human Fighter
echo Lvl: %lvl1% Money:%gp1%
echo Hit Points: %hp1%/12
echo Armor: Breastplate Armor Class: %ac1%
echo Exp: %exp1%/%expmax1%
echo Weapon: Battleaxe 1D8 Slashing
echo Stat Modifiers:
echo Strength: +%str1%
echo Dexterity: +%dex1%
echo Constitution: +%con1%
echo Intelligence: +%int1%
echo Wisdom: +%wis1%
echo Charisma: +%cha1%
echo -------------------------------------
echo 1) Continue
echo 2) Exit
echo.
set /p input=Enter:
if %input%==1 goto hf1continue
if %input%==2 exit
I expect it to create the batch file after creating an account so that you can log in later.
For your menus, I would like to introduce you to choice.exe as an alternative to Set /P. It is far better to use it when input must be any one of a small set of known values. Set /P allows the end user to enter nothing or anything, and in order to maintain control you need to build in some input verification mechanism. To find out how choice.exe works, open a cmd.exe window and enter choice /? at the prompt.
Here is a rewritten example snippet of your script, (lines 1-43) to hopefully explain why:
#Echo Off
Title Lost Mine of Phandelvor
:EnterGame
ClS
Echo(
Echo Welcome to Lost Mine of Phandelvor
Echo ----------------------------------
Echo(
Echo 1. Create Account
Echo 2. Login
Echo 3. Exit
Echo(
Choice /C 123
If ErrorLevel 3 Exit /B
If ErrorLevel 2 GoTo Login
:CreateUser
ClS
Echo(
Set "username1="
Set /P "username1=What would you like your Username to be? "
If Not Defined username1 GoTo CreateUser
:CheckForSpaces
If Not "%username1: =%"=="%username1%" (
Echo Sorry you can not use spaces in your Username.
Choice /M "Is %username1: =%" okay"
If ErrorLevel 2 GoTo CreateUser
)
If Exist "%username1%.bat" GoTo :Login
Echo(
Set "password1="
Set /P "password1=What would you like your Password to be? "
However, before you continue with your script, based upon what I said about using Set /P. The end user can currently enter anything they want as username1. We've already checked for no entry and for spaces, but you're also saving the name as a filename too, %name%.bat. Along with the decimal character codes 0 through 31, Windows filenames cannot contain any of the following characters, \/:*?"<>|, so you'd need to incorporate further verification of username1. This verification procedure would need to be implemented before line 31 of the code above.
Before you do so however, you may want to consider changing your methodology and not saving the Username to the name of a file. The reason for this is that you'd also be wise not to use filenames ending with a ., or any named CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1, LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9 either. So you would further need to include those verification checks of the input too.
Don't forget, you'll probably want to include a verification method for input entries to the %password1% prompt too!
Given the complexity involved with user input and Set /P you can see why I have recommended choice.exe as a control measure for your menus.
Ooh - so many errors!
First, add an extra line setlocal enabledelayedexpansion directly after the #echo off line. This has two effects - first, when your batch ends, your environment is restored to its original condition so that you don't get confused with variables that have been established by prior runs. second, it turns on delayed expansion mode - which is where the !variable! syntax you are using is activated, otherwise ! is simply an ordinary character.
Next, having accepted input from the ketboard with a set /p, you have no idea whether the user entered. In your validation if statements, use if "%var%"=="value" which overcomes most input problems.
Next, the syntax SET "var=value" (where value may be empty) is used to ensure that any stray trailing spaces are NOT included in the value assigned.
And a little tip for games that need a save/restore feature:
If you reserve a character as a prefix for variables-you-want-to-save (eg all variables I want to save/reload start with #) then all you need to save a game is
set #>"mygamefile.txt"
and all you need to reload a game is
for /f "usebackqdelims=" %%a in ("mygamefile.txt") do set "%%a"
To zap all # variables (useful before reloading a game) use
for /f "delims==" %%a in ('set # 2^>nul') do set "%%a="
You should look at the thousands of code examples here on SO to find out how to use subroutines - you appear to be using "spaghetti code".
This code may help with your password-checking:
for /f "tokens=1,2" %%a in (passwordfilename) do if "%%a"=="%playername%" set "playerpass=%%b"
if "%playerpass%"=="%enteredpass%" goto gameon
This uses a single password file of the form
player1 password1
player2 password2
If player1 changes password, then append the new data to the file like this:
player1 password1
player2 password2
player1 newpassword
and the above for /f construct will then set playerpass to the last occurrence of player1 found.
This should provide you with a start and obviate your need for a subsidiary batch file. You'll have enough on your plate implementing these suggestions, but you should be able then to see the wood for the trees.
And implement changes one at a time, then test and debug them. Small steps will make the process a lot easier.
I'm using the same thing in my game. You need 2 functions, 1 to load and 1 to save. The save function should look something like this:
:: My save thing
:save
(
echo %var1%
echo %var2%
) > save.sav
and the loading portion should look something like this:
< save.sav (
set /p var1=
set /p var2=
)
also, one major recommendation, put all your scripts into separate files and folders. Like a normal game, example:
- MainGame
- Launcher.bat
- Resources
- Scripts
- Save.bat
- Load.bat
- Fight.bat
- Assets
- Title.txt
this is a similar structure to what I used in my game.

How can I set the line a string is found on as a variable, and then find the contents of that line number in another file?

Okay, this is kind of complicated so ill try to explain it as best as is can.
I am currently writing a simple program for my own use using notepad.
I am using the language batch and running the program through Command Prompt.
Part of the Program lets you access an account you created with username and password:
set /p USERNAME1= Username?
findstr /n "%USERNAME1%" Usernames.txt
In Usernames.txt are the usernames of each account that has been created, one per line.
If your username is found, it is displayed along with the line number before it in the program.
It then asks for your password:
set /p PASSWORD1= Password?
This is where the problem starts. When the accounts are created, the usernames are stored, one per line, in Usernames.txt , and so are the passwords but in Passwords.txt
I need the program to check if the password you typed is the same as the password on the same line number the username is on, in Passwords.txt
I know this is complicated but if anyone can help it would be greatly appreciated!
Thanks
You're using findstr /N to get the line number of usernames.txt, which is a good start. You're getting the entire line, prefixed with the line number and a colon :.
So for /F can be used to extract the number only. The option string "tokens=1 delims=:" defines to divide the found line at the (first) :, so the line number is separated from the user name.
Finally, another for /F can be used to get the line of the passwords.txt files.
Putting all those things together, the following code snippet emerges:
set /P USERNAME1=Username?
set /P PASSWORD1=Password?
set /A LINENUMBER=0
for /F "tokens=1 delims=:" %%I in (
'findstr /N /I /X /C:"%USERNAME1%" "\path\to\usernames.txt"'
) do (
set LINENUMBER=%%I
goto :CONTINUE1
)
:CONTINUE1
set /A LINENUMBER-=1
if %LINENUMBER% lss 0 (
exit /B
) else if %LINENUMBER% equ 0 (
set SKIPPING=
) else (
set SKIPPING=skip=%LINENUMBER%
)
for /F "usebackq %SKIPPING% delims=" %%I in (
"\path\to\passwords.txt"
) do (
if "%%I" equ "%PASSWORD1%" (
goto :CONTINUE2
)
exit /B
)
:CONTINUE2
rem do something...
So the variable USERNAME1 holds the entered user name to search and PASSWORD1 the entered password.
If the user name cannot be found in usernames.txt, or the entered password does not match the found one, the script is terminated using exit /B.
Note that user names are compared in a case-insensitive manner (/I switch), but the password are compared case-sensitively.

Create a database within a bat file

I am trying to create a bat file that is in essence a database. I want to be able to enter information that is tied to a single record. When I enter a record, I want to be able to look up the record by the card number assigned to it. The code I have now doesn't really work due to the fact that the variables are not being stored properly.
This is my code:
Color 5F
#echo off
:start
cls
echo ==========================================
echo Gift Card
echo ==========================================
echo.
echo What would you like to do?
echo.
echo 1 Add Card
echo 2 Check Information
echo 3 Edit Card Balance
echo 4 Delete Card
echo.
set /p choice=Please enter choice:
if /I %choice%==1 goto 1
if /I %choice%==2 goto 2
:1
echo.
set /p var=Enter Card Number:
set /p val=Enter Amount:
set /p fname=Enter First Name:
set /p lname=Enter Last Name:
set /p cbal=Enter Current Balance:
set /p diss=Enter Date issued:
#echo set %var%=%val%=%fname%=%lname%=%cbal%=%diss% > %var%.bat
echo.
echo The data has been stored!
pause
goto start
:2
echo.
set /p var=Please enter card number:
setlocal enabledelayedexpansion
call %var%.bat
echo !%fname%! !%lname%!'s !%var%! card has $!%cbal%! on it as of !%diss%!!
pause > nul
goto start
I have tried to send the variables separately and altogether and none have worked. I am thinking it is because I do not have the delayed expansion sytax correct.
Any help is very appreciated!
Your problem seems to lie where you generate the batch file to fill the variables... You generate only one line, which does not actually assign anything to any of the variables you need.
Try changing
#echo set %var%=%val%=%fname%=%lname%=%cbal%=%diss% > %var%.bat
to be
#echo set var=%var% > %var%.bat
#echo set val=%val% >> %var%.bat
#echo set fname=%fname% >> %var%.bat
#echo set lname=%lname% >> %var%.bat
#echo set cbal=%cbal% >> %var%.bat
#echo set diss=%diss% >> %var%.bat
This should allow your variables to be loaded back properly.
Also, change
echo !%fname%! !%lname%!'s !%var%! card has $!%cbal%! on it as of !%diss%!!
to read
echo %fname% %lname%'s %var% card has $%cbal% on it as of %diss%!
You should never use both ! and % to surround variables in a batch file, only one or the other. % should be used in most cases; ! should be used when you need to read a variable inside a multi-line "code block" (for example, the result of an if statement or the body of a for loop) which is surrounded by parentheses.
Some more advice:
You can put setlocal delayedexpansion just once in the beginning of the file, right after #echo off. However, you are not doing anything in this program (yet, at least) to need delayed expansion. Delayed expansion is used to enable accessing variables with the ! symbol and is only useful inside multi-line statement bodies surrounded by parentheses. Because of that, you should get rid of it completely unless/until you actually need it, as it can cause other problems.
There is no need for the "#" symbol in any command after you call #echo off (but it won't break anything). The # symbol simply suppresses echoing of the command which it precedes, but it is redundant because all commands are silenced by default after you call echo off. For this reason, it is important to only use it on the first line when calling #echo off, so that the user does not see that command echoed.

Batch increment part of variable name

How can I increment part of a variable name?
EG. i want to increment
filename holds something like mmddyyyy-prev01-Database.mdb
and I'm trying to rename it to mmddyyyy-prev02-Database.mdb
With the code
Setlocal EnableDelayedExpansion
set /a nextFileName=!fileName:~0,13!!fileName:~13!+1
and I get the error
Missing operator.
I am using this to make a batch sub that will recursively rename the prevXX items so that the newest one is always prev01. I'm also doing regular setlocal in my method to keep the variables from getting mixed up between the deeper calls
I'm going the hard way:
#ECHO OFF &SETLOCAL disableDelayedExpansion
FOR /f "delims=" %%x IN ('DIR /b /a-d /o-n *-prev*-Database.mdb') DO (
FOR /f "tokens=1-3*delims=v-" %%a IN ("%%~x") DO (
FOR /f "tokens=*delims=0" %%e IN ("0%%c") DO (
FOR /f %%f IN ('SET /a %%e+1') DO (
IF %%f LEQ 9 (
ECHO REN "%%~x" "%%~a-%%~bv0%%~f-%%~d"
) ELSE (
ECHO REN "%%~x" "%%~a-%%~bv%%~f-%%~d"
)
)
)
)
)
Just remove the ECHOs to make it working.
SET /A won't allow you do this.
You'll have to break up into two lines, like this:
SET BaseFileName=!FileName:~0,13!
SET /A Counter=!FileName:~13!+1
Then, put the pieces back together:
SET NextFileName=%BaseFileName%%Counter%-Database.mdb
NOTE: This will not handle your leading 0...you'll have to write more code for that.
...
set filename=mmddyyyy-prev01-Database.mdb
call :nextname
ren %filename% %newname%
...
:nextname
set /a newname=1%filename:~13,2%+1
set newname=%filename:~0,13%%newname:~-2%%filename:~15%
goto :eof
Whether you'd use ren %filename% %newname% or ren !filename! !newname! is a matter of context. You've posted insufficient code to be certain. If, as I suspect, you are executing the ren in a loop, then you would need the !var! form and delayedexpansion (with which you appear familiar.) Within the subroutine :nextname, the %var% form should be used.
but remember that you need to rename your existing files in reverse-alphabetical order, so
mmddyyyy-prev03-Database.mdb becomes mmddyyyy-prev04-Database.mdb
mmddyyyy-prev02-Database.mdb becomes mmddyyyy-prev03-Database.mdb
mmddyyyy-prev01-Database.mdb becomes mmddyyyy-prev02-Database.mdb

Variables in loops Dont Work, Batch

This is the new Script and it Still Doesn't Work
I Get The syntax of the command is incorrect.
on FOR /F "USEBACKQ tokens=*" %%A IN (TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command") DO (
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "C:\Windows\System32\tasks\at%num%" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "C:\Windows\System32\tasks\at!num! ^| FIND "Command"`) DO (
set var=%%A
ECHO %var%
SET /a num=%num%+1
PAUSE
)
GOTO:START
To understand your code, I'm going to break it down into logic first then try to solve it. Let me know if I miss a detail...
Set num var to 0
Begin :Loop
set num var to its current value ::NOT NEEDED - You've specified this prior to the GOTO
increment num var by +1
if myfolder\at* file exists then read at%num% and find a string then output that line to %tmp%\1.txt ::Need quotations on file location.
set F var to the line stored in %tmp%\1.txt
set F="%%F: =%%" ::Please explain what you are trying to do with this command.
set F to start on 10th character and remove the last 11 characters from the line.
echo the variable
If it doesn't exist, exit, but if it does return to :Loop
You should tell us what you are attempting. If it is as simple as saving a variable from a text file output, set F=<file.txt will work. If it didn't, then something happened prior to that command. Still... what is set F="%%F: =%%"?
Unless you are using a FOR loop variable, there is no need to use %% on each end of the variable.
If this were a FOR loop, it would look like this:
SETLOCAL ENABLEDELAYEDEXPANSION
set num=1
:START
IF NOT EXIST "myFolder\at%num%.txt" (GOTO:EOF)
FOR /F "USEBACKQ tokens=*" %%A IN (`TYPE "myFolder\at%num%.txt" ^| FIND /i "string"`) DO (
PAUSE
SET var=%%A
ECHO !var!
PAUSE
SET var=!var: =!
ECHO !var!
PAUSE
SET var=!var:~10,-11!
ECHO !var!
PAUSE
SET /a num=!num!+1
ECHO !num!
PAUSE
)
GOTO:START
One good practice to check if commands are working, such as SET, insert an ECHO on the variable and a PAUSE right after each time you believe the variable should be changed. This will track what has changed on the variable so you can see if your command was correct and the changes were made.
I'd suggest using Batch's inbuilt function for loops, see here.
Conditionally perform a command for a range of numbers
Syntax
FOR /L %%parameter IN (start,step,end) DO command
Or maybe iterating over files in a folder would be better for what you are trying to do?
Loop through files (Recurse subfolders)
Syntax
FOR /R [[drive:]path] %%parameter IN (set) DO command
Or iterating over file contents?
Loop command: against a set of files - conditionally perform
a command against each item.
Syntax
FOR /F ["options"] %%parameter IN (filenameset) DO command
FOR /F ["options"] %%parameter IN ("Text string to process") DO command
This site has plenty of examples here which should point you in the right direction.
There are a few issues with your code, I've amended as follows to get the variable populated with the contents of the temp file.
set num=0
:Loop
set /a num=%num%+1
if exist "myFolder\at*" (
TYPE "myFolder\at%num%" | FINDSTR "\<Command\>" > "%temp%\1.txt"
set /P F=<"%TEMP%\1.txt"
Echo %F%
Pause
)
I don't know if this is the problem, but have you tried enabling:
setlocal enabledelayedexpansion
Then, inside the loop (or the IF(...)), you use !foo! to signify environment variables instead of %foo%.
See setlocal /? and set /? for more information.