Retrieving variables from .txt error; Batch - variables

:LoadSelect1
set /p Name=Enter character to load:
cls
if EXIST "%Name%_Savefile.txt" goto Load
goto LoadError
:Load
for /f "tokens=1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26" %%a in (%Name%_Savefile.txt) do call :Process %%a %%b %%c %%d %%e %%f %%g %%h %%i %%j %%k %%l %%m %%n %%o %%p %%q %%r %%s %%t %%u %%v %%w %%x %%y %%z
goto Stats
:Process
set Location=%1
set Name=%2
set Gender=%3
set Age=%4
set Gold=%5
set Hunger=%6
set Illness=%7
set Wounds=%8
set CHP=%9
set MHP=%10
set CMP=%11
set MMP=%12
set DMG=%13
set DFN=%14
set INT=%15
set DEX=%16
set STR=%17
set Head=%18
set Shoulder=%19
set Neck=%20
set Chest=%21
set Glove=%22
set Leg=%23
set Feet=%24
set LTWP=%25
set RTWP=%26
Above code is used to retrieve variables saved to a .txt file in my batch script. Variables save fine to individual lines. When Call :Process function is used, %1 is applied for %1, and "%1X" become %1 with number attached. Meanwhile %2-9 are blank, and %2X are blanks with number attached. Solution would be great.
Pastebin of full code
To recreate: Run as batch file. Go through prompts until section with 9 choices. Type "Save". Close and reopen. Go to Load option. Type in name from previous. View errors.

It would be easier if you save your savefile.txt in this format :
savefile.txt
Location=AAAA
Name=BBBB
Gender=CCCC
Age=DDDD
Gold=EEEE
Hunger=FFFF
Illness=GGGG
Wounds=HHHH
and then to set the variables saved in savefile.txt :
for /f "delims=" %%a in (savefile.txt) do set %%a
You can also save your savefile as .bat then it will look like this :
set Location=AAAA
set Name=BBBB
----
and with the call:savefile.bat all your Vars will be evaluated

Related

batch script for file system: use of for-loop variable in another nested for-loop

the last 4-5 hours I spent trying to get my script fixed, and tried several things, but it still doesn't work as supposed. Here is the working part:
#echo off
rem automatically sort MP3s into an existing structure or add folders if needed
rem example of MP3-file pattern: Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3
SETLOCAL
rem set variables
SET "source=g:\music\folder"
SET "str=Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3"
SET "test=%source%\%str%"
rem split the filename from the remaining path. Take the left part
rem and assign it to %band% while the right part gets assigned to %song%
FOR /f "delims=" %%i IN ("%test%") DO SET "result=%%~nxi"
SET "band=%result: - =" & SET "song=%"
rem If there is no such folder (%band%), create it
IF not exist "%source%\%band%" MD "%source%\%band%"
rem As soon as there definetely is a fitting folder
rem move the file over there.
MOVE /-Y "%source%\%result%" "%source%\%band%"
The next step would be to enhance the code by a for-loop so I don't have to edit the script for every single one of my 3k+ files ;)
I tried really hard to get this code going, but failed:
#echo off
SETLOCAL
SET "source=g:\music\folder"
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
SET "band=!result: - =" & SET "song=%"
IF not exist "%source%\%band%" MD "%source%\%band%"
MOVE /-Y "%source%\%result%" "%source%\%band%"
)
pause
So I added a for-loop and %%f was correctly filled at first and wasn't in the next for-loop.
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
That resulted in: "g:\music\folder\Wu-Tang Clan - Gravel Pit (LP Version Clean).mp3"
Like it was supposed to. But after that
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
result and every following variable was empty, always.
I tried to fix it with a second variable as a 'helper':
FOR %%f IN (%source%\*.mp3) DO (
SET "helper=%%f"
FOR /f "delims=" %%i IN ("%helper%") DO SET "result=%%~nxi"
Even added 'enabledelayedexpansion' after I read about that and went for
FOR /f "delims=" %%i IN ("!helper!") DO SET "result=%%~nxi"
still doesn't work.
Now I could really need some help and would really appreciate it :)
regards Phoenix
Next code snippet could work. Note that the SET "band=%result: - =" & SET "song=%" trick can't be performed using ! delayed expansion unlike %-expansion. Therefore, that command is moved to the :myset subroutine and executed via call command.
#echo off
SETLOCAL EnableExtensions EnableDelayedExpansion
SET "source=g:\music\folder"
FOR %%f IN (%source%\*.mp3) DO (
echo %%f
FOR /f "delims=" %%i IN ("%%f") DO SET "result=%%~nxi"
call :myset
IF not exist "%source%\!band!" MD "%source%\!band!"
MOVE /-Y "%source%\!result!" "%source%\!band!"
)
goto :skipMyset
:myset
SET "band=%result: - =" & SET "song=%"
goto :eof
:skipMyset
pause
Resources (required reading):
(command reference) An A-Z Index of the Windows CMD command line
(additional particularities) Windows CMD Shell Command Line Syntax
(special page) EnableDelayedExpansion

Batch: variable definition useable in count loop

In my batch I want to copy a variable amount of source- to target destinations.
I want to define like this:
#setlocal EnableDelayedExpansion
set source1="C:\folder1"
set target1="f:\folder1"
set source2="C:\folder2"
set target2="f:\folder2"
...
set sourcen="C:\foldern"
set targetn="f:\foldern"
Dependently from a defined amount of folders
set numFolder=5
I want to go through the folders in a loop:
set /a COUNT=0
:LOOP
echo %COUNT%
set /a COUNT+=1
rem write the NAME of the parameter variable (source1,source2 etc.) in nameor
set "nameor=source%COUNT%"
rem write the VALUE of the parameter variable (source1,source2 etc.) into origin ("C:\folder1", "C:\folder2")
set "origin=%nameor%"
echo %origin%
if %COUNT% lss %numFolder% goto LOOP
When I show
echo %nameor%
I get what I expectet: source1, source2 etc.
but
echo %%%origin%%%
only provides
source1
instead of the expected value
"C:\folder1"
I thought, that I could resolve this by using DelayedExpansion but what did I miss?
To avoid confusion for me, I change the "origin" to "source". E.g. set "origin=%nameor%" changed to set "source=%nameor%".
To print out "C:\folder1" to "C:\foldern", you should use echo !%source%!, else you will just see "source1" to "sourcen".
Your problem is just about array element management. Try this:
#echo off
setlocal EnableDelayedExpansion
rem Define the two arrays
set i=0
for %%a in ("C:\folder1=f:\folder1"
"C:\folder2=f:\folder2"
"C:\foldern=f:\foldern") do (
set /A i+=1
for /F "tokens=1,2 delims==" %%b in (%%a) do (
set source!i!="%%a"
set target!i!="%%b"
)
)
rem Show up to numFolder elements of both arrays
set numFolder=5
for /L %%i in (1,1,%numFolder%) do (
echo %%i- Source%%i=!source%%i!, Target%%i=!target%%i!
)
The first part is equivalent to your series of individual element assignments. In this way is easier to add new pairs of values.
For further description on array management in Batch files, see: Arrays, linked lists and other data structures in cmd.exe (batch) script

Export batch variables to text file

I was recently given the advice to export variables from a batch script to a text file using
set $>savefile
and returning said variables upon another startup using
for /f "delims=" %%a in (savefile) do set %%a
In implementation, this is not creating a file with the variables, resulting in error in the script, which closes the batch. To remedy the closing, I created a check to display an error message, but still cannot get the script to export variables into a file.
Variables
::Variables
set Location=Und
set Name=Und
set Gender=Und
set Age=Und
set Gold=0
set Hunger=Satisfied
set Illness=None
set Wounds=None
set CHP=10
set MHP=10
set CMP=0
set MMP=0
set DMG=(%STR%/5)+%RTWPDMG%
set DFN=0+%HeadAR%+%NeckAR%+%Shoulder%+%Chest%+%Glove%+%Leg%+%Feet%
set INT=1
set DEX=1
set STR=1
set Head=----
set Shoulder=----
set Neck=----
set Chest=Shirt
set Glove=----
set Leg=Pants
set Feet=Shoes
set LTWP=----
set RTWP=----
goto Start
Save script
::Save
:Save
cls
set $Location=%Location%
set $Name=%Name%
set $Gender=%Gender%
set $Age=%Age%
set $Gold=%Gold%
set $Hunger=%Hunger%
set $Illness=%Illness%
set $Wounds=%Wounds%
set $CHP=%CHP%
set $MHP=%MHP%
set $CMP=%CMP%
set $MMP=%MMP%
set $DMG=%DMG%
set $DFN=%DFN%
set $INT=%INT%
set $DEX=%DEX%
set $STR=%STR%
set $Head=%Head%
set $Shoulder=%Shoulder%
set $Neck=%Neck%
set $Chest=%Chest%
set $Glove=%Glove%
set $Leg=%Leg%
set $Feet=%Feet%
set $LTWP=%LTWP%
set $RTWP=%RTWP%
set $>%Name%_Savefile.txt
cls
echo SAVED
echo.
echo.
pause
Goto Start
And the load script
::Select Character to Load
:LoadError
Echo INVALID NAME
echo.
echo.
echo.
echo.
goto LoadSelect1
:LoadSelect
cls
goto LoadSelect1
:LoadSelect1
set /p Name=Enter character to load:
goto Load
:Load
cls
if EXIST %Name%_Savefile.txt goto LoadSuccess
goto LoadError
:Load
for /f "delims=" %%a in %Name%_Savefile.txt do set %%a
goto Stats
Am I missing something? I'd like all variables beginning with $ to be targeted without needing to list each one.
Bonus Question:
If I use $Variable for the original variables, are they still called using %Variable%? If so, it'd cut down quite a bit of clutter.
--I realize batch is a sub-optimal language to script in, but it is the only one I am familiar with. I am currently working on lua and C++, and plan on practicing the two by converting the batch file later.
EDIT: The file is created, but only contains $ in line 1 and nothing else. I assume I have misunderstood the use of the variable export command.
It is quite simple say if you had %test% as your variable. (But it can be %% any thing) You should then do this:
echo %test%
echo %test% >nameofyourtextfile.txt
Then to read the you should use:
for /f "delims=" %%x in (nameofyourtextfile.txt) do set "test=%%x"
echo %test%
works for the first line of the text file and >> sends the variable to last line. So you could use these like so:
echo %test1% > nameofyourtextfile.txt
echo %test2% >> nameofyourtextfile.txt
echo %test3% >> nameofyourtextfile.txt
To load from different lines you would use:
for /F "tokens=1,2,3" %%i in (nameofyourtextfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set test1=%1
set test2=%2
set test3=%3
You could add more tokens like so:
for /F "tokens=1,2,3,4,5" %%i in (nameofyourtextfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set test1=%1
set test2=%2
set test3=%3
set test4=%4
set test5=%5
If you do it the way you posted, what you have is (just a extract)
in your main code set Wounds=None
in your save code set $Wounds=%Wounds% set $>filename
in your load code for %%a .... set %%a that gets translated to set $Wounds=None
At the end, you have not assigned a loaded value to %Wounds%, so an aditional set Wounds=%$Wounds% is needed.
I think the advice on using $ you received was an advice on using a common prefix to all the variables you want to save, so, you can send them and load them from a file with little effort. You can use $ or whatever other thing you want as long as it is a valid sintax and you change all the variables that you want save/load to that sintax.
By example
call :initializeCharacter
....
call :save
....
call :load
:initializeCharacter
set "ch.Name=Und"
set "ch.Gender=Und"
....
exit /b
:save
set ch.>"c:\savedGames\save.txt"
exit /b
:load
for /f "usebackq delims=" %%a in ("c:\savedGames\save.txt") do set "%%a"
exit /b
When the load function gets called, the variables (named ch.whatever and saved as ch.whatever) get overwritten on file read. That way, the variables in your code, what you save and what you load, all, have the same names. No need to set $myVar=%myVar% on save or set myVar=%$myVar%on load
And use $, ch., .... or whatever prefix you prefer in all the variables that needs to be saved/loaded in a block. What you don't want to save/load should have names that do not match the prefix used in the set prefix>file. Better option is to use different prefixes for different domain/level/conceptual element/...

How to create new variable out of current variable contents

I have a variable "var1" with contents of "sharp=soothe"
var1=sharp=soothe
How do I create a new variable using only var1 contents to get this
sharp=soothe
I want to use the set command somehow like this
set %var1%=
but I can't get further than this. I hope I don't have to search for strings before and after the = sign. I thought there would be a faster way than that.
OK, I am so close. I found some other code I'm using and this nearly works for an infinite number of variables but the set command syntax is wrong again.
set var1=unfilter=rem
set var2=mdegrain=rem
set n=0
:parseArgs2
set /a n+=1
if defined var%n% (
set %var%n%%
shift /1
goto :parseArgs2
)
Just remove one character from your attempt :-)
set %var1%
If you have an "array" of variables: var1, var2, ... var20, then you can use a FOR /L loop with delayed expansion:
setlocal enableDelayedExpansion
rem define your variables here ...
for /l %%N in (1 1 20) do set !var%%N!
Or if you have a series of randomly named variables, a simple FOR will do:
setlocal enableDelayedExpansion
rem define your variables here ...
for %%V in (varA varB varC varD) do set !%%V!
update in response to add-on question
I don't see why you are using SHIFT, unless there is other code you haven't shown. I removed the SHIFT.
set var1=unfilter=rem
set var2=mdegrain=rem
set n=0
:parseArgs2
set /a n+=1
if defined var%n% (
call set %%var%n%%%
goto :parseArgs2
)
or
setlocal enableDelayedExpansion
set var1=unfilter=rem
set var2=mdegrain=rem
set n=0
:parseArgs2
set /a n+=1
if defined var%n% (
set !var%n%!
goto :parseArgs2
)
Try this:
set var1=sharp=soothe
for /f "tokens=*" %%a in ("%var1%") do set %%a
echo %sharp%
or just:
for %%a in ("%var1%") do set %%a
Perhaps is this what you want?
#echo off
setlocal EnableDelayedExpansion
set var1=unfilter=rem
set var2=mdegrain=rem
set var10=resize=rem
for /F "tokens=1* delims==" %%a in ('set var') do set %%b
In this method does not matter the number of defined variables nor its order; all defined variables are always processed.
EDIT: Below is the output when an ECHO command is placed before the set %%b:
set unfilter=rem
set resize=rem
set mdegrain=rem

How to split an ip address into seperate octets and perform arithmetic in cmd

What I am trying to do is configure some vlan scopes via cmd. What I have accomplished so far is to retrieve the IP Address of the Domain Controller and remove the space in front of the value. I have accomplished this using the following commands:
rem extract ip address via local cmd
for /f "tokens=2 delims=:" %i in ('ipconfig ^| find /i "IPv4 Address"') do set ip_address=%i
example result: set ip_address= 10.0.0.25
rem remove empty space from ip address var
set ip_address=%ip_address: =%
echo %ip_address% now results in 10.0.0.25 without the space in front.
What I would like to do next is split the ip_address variable in separate octet variables so that arithmetic can be performed on the octet of choice.
For example: 10.0.0.25 could then be manipulated to reflect 10.[+100].0.[-24]
the desired result would then be 10.100.0.1
I would prefer to accomplish this strictly using windows command line but if a better method exits I am open to suggestions.
Thanks in advance
Joel
Try this to split up the octets into variables.
#echo off
set "ip=10.0.0.25"
SET "offsets=0.100.0.-24"
#echo off
for /f "tokens=1-4 delims=. " %%a in ("%ip%") do (
set octetA=%%a
set octetB=%%b
set octetC=%%c
set octetD=%%d
)
FOR /f "tokens=1-4 delims=." %%a in ("%offsets%") do (
SET /a octetA+=%%a
SET /a octetB+=%%b
SET /a octetC+=%%c
SET /a octetD+=%%d
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
This is the same solution of foxidrive, but squashed a little... :)
#echo off
set "ip= 10.0.0.25"
SET "offsets=0.100.0.-24"
for /F "tokens=1-4 delims=. " %%a in ("%ip%") do (
for /F "tokens=1-4 delims=." %%i in ("%offsets%") do (
set /A octetA=%%a+%%i, octetB=%%b+%%j, octetC=%%c+%%k, octetD=%%d+%%l
)
)
echo "%octetA%","%octetB%","%octetC%","%octetD%"
pause
Are you aware of autohotkey?
Also, you could try a powershell script.