Can I make a negative value in batch display as 0? - batch-file

I am coding a store generator for a table top RPG. I have it set up to generate different content based on which faction you select, a random roll to determine how well the shop is doing (poor, average, good, excellent), and then randomly determines the amount of an item in the shop.
However to make certain items more or less likely to show up I set it to have say 3d6-5 Arrows, this results in a minimum of -2 and a maximum of 13 arrows. Naturally a store cannot have -2 arrows. Is there any way to be able to still set a minimum and maximum range for a variable, but have 0 be the lowest, or make any negative value display as 0?

if %val% lss 0 set /a val=0
is one way
Here's a more comprehensive version:
#ECHO OFF
SETLOCAL
SET val=5
ECHO ==== :setlt =====
CALL :setlt val 3&CALL :showval %val% val
CALL :setlt val 6&CALL :showval %val% val
CALL :setlt val 5&CALL :showval %val% val
CALL :setlt val 3 27&CALL :showval %val% val
CALL :setlt val 6 1&CALL :showval %val% val
CALL :setlt val 5 11&CALL :showval %val% val
ECHO ==== :setgt =====
CALL :setgt val 3&CALL :showval %val% val
CALL :setgt val 6&CALL :showval %val% val
CALL :setgt val 5&CALL :showval %val% val
CALL :setgt val 3 27&CALL :showval %val% val
CALL :setgt val 6 1&CALL :showval %val% val
CALL :setgt val 5 11&CALL :showval %val% val
ECHO ==== :setra =====
CALL :setra val 3 8&CALL :showval %val% val
CALL :setra val 8 11&CALL :showval %val% val
CALL :setra val 2 4&CALL :showval %val% val
CALL :setra val 3 8 6&CALL :showval %val% val
CALL :setra val 8 11 6&CALL :showval %val% val
CALL :setra val 2 4 6&CALL :showval %val% val
CALL :setra val 3 8 6 7 &CALL :showval %val% val
CALL :setra val 8 11 6 7&CALL :showval %val% val
CALL :setra val 2 4 6 7&CALL :showval %val% val
CALL :setra val 3 8 "" 6&CALL :showval %val% val
CALL :setra val 8 11 "" 6&CALL :showval %val% val
CALL :setra val 2 4 "" 6&CALL :showval %val% val
ECHO ==== add some extras =====
SET val=20&CALL :disp val 1 8 "" "" "The strange die rolls "
SET val=-4&CALL :disp val 0 8 "" "" "" "ghouls flee in fear"
SET val=-4&CALL :disp val 0 8 "" "" "There are " "arrows in stock"
SET val=-4&CALL :dispgz val 0 8 "" "" "There are " "arrows in stock"
SET val=14&CALL :dispgz val 0 8 "" "" "There are " "arrows in stock"
GOTO :EOF
:: set a variable %1 to %3 if it is less than %2
:setlt
CALL SET $1=%%%1%%
IF %$1% lss %2 SET "%1=%~3"
IF NOT DEFINED %1 SET "%1=%~2"
goto :eof
:: set a variable %1 to %3 if it is greater than %2
:setgt
CALL SET $1=%%%1%%
IF %$1% gtr %2 SET "%1=%~3"
IF NOT DEFINED %1 SET "%1=%~2"
goto :eof
:: set a variable %1 to %4 if it is less than %2 or %5 if it is greater than %3
:setra
CALL ECHO if %%%1%% .lt. %2 SET to "%~4" IF %%%1%% .gt. %3 to "%~5"
CALL :setlt %1 %2 %~4
CALL :setgt %1 %3 %5
goto :eof
:showval
CALL ECHO value was %1 is now %%%2%%
SET %2=%1
GOTO :eof
:: Display with limits.
:disp
setlocal
CALL SET $2=%%%1%%
CALL :setra $2 %2 %3 "%~4" "%~5"
ECHO %~6%$2% %~7
endlocal
GOTO :eof
:: Display with limits - but only if resolved value is greater than zero
:dispgz
setlocal
CALL SET $2=%%%1%%
CALL :setra $2 %2 %3 "%~4" "%~5"
IF %$2% gtr 0 ECHO %~6%$2% %~7
endlocal
GOTO :eof
Here's the output:
==== :setlt =====
value was 5 is now 5
value was 5 is now 6
value was 5 is now 5
value was 5 is now 5
value was 5 is now 1
value was 5 is now 5
==== :setgt =====
value was 5 is now 3
value was 5 is now 5
value was 5 is now 5
value was 5 is now 27
value was 5 is now 5
value was 5 is now 5
==== :setra =====
if 5 .lt. 3 SET to "" IF 5 .gt. 8 to ""
value was 5 is now 5
if 5 .lt. 8 SET to "" IF 5 .gt. 11 to ""
value was 5 is now 8
if 5 .lt. 2 SET to "" IF 5 .gt. 4 to ""
value was 5 is now 4
if 5 .lt. 3 SET to "6" IF 5 .gt. 8 to ""
value was 5 is now 5
if 5 .lt. 8 SET to "6" IF 5 .gt. 11 to ""
value was 5 is now 6
if 5 .lt. 2 SET to "6" IF 5 .gt. 4 to ""
value was 5 is now 4
if 5 .lt. 3 SET to "6" IF 5 .gt. 8 to "7"
value was 5 is now 5
if 5 .lt. 8 SET to "6" IF 5 .gt. 11 to "7"
value was 5 is now 6
if 5 .lt. 2 SET to "6" IF 5 .gt. 4 to "7"
value was 5 is now 7
if 5 .lt. 3 SET to "" IF 5 .gt. 8 to "6"
value was 5 is now 5
if 5 .lt. 8 SET to "" IF 5 .gt. 11 to "6"
value was 5 is now 8
if 5 .lt. 2 SET to "" IF 5 .gt. 4 to "6"
value was 5 is now 6
==== add some extras =====
if 20 .lt. 1 SET to "" IF 20 .gt. 8 to ""
The strange die rolls 8
if -4 .lt. 0 SET to "" IF -4 .gt. 8 to ""
0 ghouls flee in fear
if -4 .lt. 0 SET to "" IF -4 .gt. 8 to ""
There are 0 arrows in stock
if -4 .lt. 0 SET to "" IF -4 .gt. 8 to ""
if 14 .lt. 0 SET to "" IF 14 .gt. 8 to ""
There are 8 arrows in stock
And now I'm free to waffle a bit...
After setting val to 5, there are many lines of the basic format
CALL :setlt val 3&CALL :showval %val% val
The routine :showval shows the current value of val and then resets it to its original value. In that way, I could report the result of the preceding CALL and reset the value to whatever value I chose (but I didn't use that feature...)
The parameters of the :setlt calls are variable, limit, forced_value - where forced_value is optional. If the forced value is not specified, the limit will be used.
So :setlt with parameters of val 3 will set the value of val to 3 if its current value is less than 3 - but if the parameters were val 6 1 then if the current value of val is less than 6, its value will be changed to 1.
So the :showval routine shows the result in each case, then resets val to 5.
:setgt is similar, just setting the value if the current value is greater than rather than less than.
Next group is the :setra which has parameters var minval maxval forceifltmin forceifgtmax - the only kink being that if forceifltmin is not used but forceiflmax is used, then forceifltmin must be an empty parameter ("").
I've added the call echo... line at the start of :setra purely to show what's happening - it's useful for debugging. Just REM or :: that line so you can turn debugging on or off.
(Tip: with debug-lines, you could try
set "debug=REM "
%debug%echo this is a debug line
Simply set debug to either REM or nothing to turn your debugging lines off or on)
Last is the :disp and :dispgz routines. These are very slightly different. They deliberately don't change the value of the variable and are designed to display the value as if it was in the range, There are an additional two parameters - both optional being the text-before and text-after value. Both should be supplied "quoted".
This time, there's simply a display of text-beforevalue text-after so you can build messages as shown.
If you don't want to display a line containing a value unless the value after applying the range-checks is >0 then use :dispgz

Related

Is it possible to make a randomly generated variable in batch? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
Currently I am making a game in batch that has randomly generated worlds. I'm currently working on biome generation, and I'm trying to figure out a way to have each variable generated, so the variables will look like %biomenum[0,0]%, %biomenum[0,1]%, and going maybe as far as %biomenum[512,512]% and as low as %biomenum[-512,-512]
The code that I have currently generates the biome for 9 different chunks, but it doesn't make the variables itself, and typing this out for each chunk between -512, -512 and 512, 512 doesn't seem all that plausible
rem 0x 0y
set /A biomenum0x0y = %RANDOM% * 16 / 32768 + 1
rem 0x 1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenum0x1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenum0x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenum0x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenum0x1y = biomenum0x0y - 1
rem 1x 1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenum1x1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenum1x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenum1x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenum1x1y = biomenum0x0y - 1
rem 1x 0y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenum1x0y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenum1x0y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenum1x0y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenum1x0y = biomenum0x0y - 1
rem 1x -1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenum1xneg1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenum1xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenum1xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenum1xneg1y = biomenum0x0y - 1
rem 0x -1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenum0xneg1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenum0xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenum0xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenum0xneg1y = biomenum0x0y - 1
rem -1x -1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenumneg1xneg1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenumneg1xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenumneg1xneg1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenumneg1xneg1y = biomenum0x0y - 1
rem -1x 0y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenumneg1x0y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenumneg1x0y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenumneg1x0y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenumneg1x0y = biomenum0x0y - 1
rem -1x 1y
set /A nextbiomenum = %RANDOM% * 4 / 32768 + 1
if /I "%nextbiomenum%" EQU "1" set /A biomenumneg1x1y = biomenum0x0y + 1
if /I "%nextbiomenum%" EQU "2" set /A biomenumneg1x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "3" set /A biomenumneg1x1y = biomenum0x0y + 0
if /I "%nextbiomenum%" EQU "4" set /A biomenumneg1x1y = biomenum0x0y - 1
echo %biomenumneg1xneg1y% is the biome for -1,-1
echo %biomenumneg1x0y% is the biome for -1, 0
echo %biomenumneg1x1y% is the biome for -1, 1
echo %biomenum0xneg1y% is the biome for 0, -1
echo %biomenum0x0y% is the biome for 0, 0 -the starting chunk-
echo %biomenum0x1y% is the biome for 0, 1
echo %biomenum1xneg1y% is the biome for 1, -1
echo %biomenum1x0y% is the biome for 1, 0
echo %biomenum1x1y% is the biome for 1, 1
How would I be able to automate the creation of variables, so I don't have to type out all 1,048,576 chunks?
*Note: This question was edited so it made more sense. The original was a very long explanation that I made on 3 hours of sleep, and I apologize for that. Hopefully this is a bit more easy to understand.
Your explanation is pretty confusing, both in what you want to get and the way to obtain it...
When you have a series of variables with the same name and you want to select one variable based on the value of another variable (called index), then the name for such a data structure is array. If the array elements are selected by just one index variable (one dimensional array), then it is usually called vector. If the array elements are selected by two or more indices (multi-dimensional array), then it is called matrix.
In computer programs the usual way to repeat the same code over a range of values that are all processed in the same way is via the FOR statement/construct/command. The FOR control variable is placed in the code in the place of the varying value. The usual way to process a series of array elements is via a FOR command and place its control variable as the index of the array element.
The way to process array elements in Batch file programs is described at this answer.
The next Batch file obtain a result equivalent than your example code, but using a two-dimensional array and two nested FOR commands:
#echo off
setlocal EnableDelayedExpansion
rem 0x 0y
set /A biomenum0x0y = %RANDOM% * 16 / 32768 + 1
rem The rest!
for %%x in (neg1 0 1) do (
for %%y in (neg1 0 1) do (
set /A nextbiomenum = !RANDOM! * 4 / 32768 - 1, biomenum%%xx%%yy = biomenum0x0y + nextbiomenum %% 2
)
)
echo %biomenumneg1xneg1y% is the biome for -1,-1
echo %biomenumneg1x0y% is the biome for -1, 0
echo %biomenumneg1x1y% is the biome for -1, 1
echo %biomenum0xneg1y% is the biome for 0, -1
echo %biomenum0x0y% is the biome for 0, 0 -the starting chunk-
echo %biomenum0x1y% is the biome for 0, 1
echo %biomenum1xneg1y% is the biome for 1, -1
echo %biomenum1x0y% is the biome for 1, 0
echo %biomenum1x1y% is the biome for 1, 1
The results obtained by this code are not exactly the same than your code. In your code you add 1 when random is 1 and subtract 1 when random is 4 (and ignore 2 and 3). In my simplification I generate a number between -1 and 2 (instead of 1 to 4) and add 1 when random is 1 and subtract 1 when random is -1 (and ignore 0 and 2); this is done taking the remainder (mod, % operator) of the number divided by 2. The statistical result is, however, the same...
Antonio
PS - I suggest you to use the standard array notation with the subscripts enclosed in square braquets, (like %biomenum[1,0]% or %biomenum[1][0]%instead of %biomenum1x0y% ) for the reasons explained at this post.

Alternative for "msg" command in .bat file for Windows 10 (64 bit)

I wrote a small timer-script as a .bat-file, which reminds me (16 times) every 30 minutes (1800 sec) in a pop-up messagebox to "Move!". The script works fine on Windows 7 (32 bit) Systems, but it seems that the "msg" command canĀ“t be used or is not existent for 64-bit Systems. Is there any alternative to this command or way to replace that command easily?
set TIMER=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)
set USERS=(%username%)
set MESSAGE=Move!
for %%i in %TIMER% do call :doit
:doit
for %%i in %USERS% do msg %%i %MESSAGE%
timeout /t 1800 /nobreak
goto:eof
You could create a temporary VBS script, run it then delete it.
See Example MessageBox
At the bottom of your program include:
exit /b
:msg
set tempPath=%temp%\msgbox.vbs
echo msgbox "%message%" > %tempPath% && %tempPath% && del %tempPath%
goto:eof
You can then use it through your script like so:
set message=Hello World
call:msg
So in your case:
set TIMER=(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16)
set USERS=(%username%)
set MESSAGE=Move!
for %%i in %TIMER% do call :doit
:doit
set message=%MESSAGE%
call:msg
timeout /t 1800 /nobreak
goto:eof
exit /b
:msg
set tempPath=%temp%\msgbox.vbs
echo msgbox "%message%" > %tempPath% && %tempPath% && del %tempPath%
goto:eof

Format a hexadecimal sequence in a cmd.exe batch file

In a Windows cmd script (aka bat script), I have a FOR /L loop from 1 to 8, where I need to do a bit shift and somehow format a variable as a hexadecimal number (which if you ask, is a single CPU identifier bit to feed into /AFFINITY).
I can't figure out how to do the last step. This is my loop.cmd file:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /L %%i IN (1,1,8) DO (
SET /A "J=1<<%%i"
ECHO %%i and !J!
)
which does everything but format a hex number:
1 and 2
2 and 4
3 and 8
4 and 16
5 and 32
6 and 64
7 and 128
8 and 256
expected output is:
1 and 2
2 and 4
3 and 8
4 and 10
5 and 20
6 and 40
7 and 80
8 and 100
How do you format a hexadecimal number?
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
FOR /L %%i IN (1,1,8) DO (
SET /A "J=1<<%%i"
CALL :DECTOHEX J
ECHO %%i and !J!
)
GOTO :EOF
:DECTOHEX VAR
SET "DEC=!%1!"
SET "HEX="
:NEXT
SET /A DIGIT=DEC%%16, DEC/=16
SET "HEX=%DIGIT%%HEX%"
IF %DEC% NEQ 0 GOTO NEXT
SET "%1=%HEX%"
EXIT /B
EDIT: Reply to the comment
Previous solution works correctly when the shifted value have just one bit on, as stated in the question. If the shifted value may have several bits on then a more general decimal-to-hexadecimal conversion is required, like the one below:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
REM DEFINE THE HEXA DIGITS
SET "HEXA=0123456789ABCDEF"
FOR /L %%i IN (1,1,8) DO (
SET /A "J=3<<%%i"
CALL :DECTOHEX J
ECHO %%i and !J!
)
GOTO :EOF
:DECTOHEX VAR
SET "DEC=!%1!"
SET "HEX="
:NEXT
SET /A DIGIT=DEC%%16, DEC/=16
SET "HEX=!HEXA:~%DIGIT%,1!%HEX%"
IF %DEC% NEQ 0 GOTO NEXT
SET "%1=%HEX%"
EXIT /B
#echo off
setlocal enabledelayedexpansion
set x=2
set n=1
set /a result=n
for /l %%a in (1,1,10) do (
set /a result*=x
if "!result:~0,1!"=="1" set result=!result:16=10!
echo %%a and !result!
)
output:
1 and 2
2 and 4
3 and 8
4 and 10
5 and 20
6 and 40
7 and 80
8 and 100
9 and 200
10 and 400

Using the batch command %random% to get to a random spot on the file

Is it possible to use the %random% command to go to a random spot on the batch file? For example:
set /p input=%random%
if %input%==[whatever the random number generated... (example 1004] goto a
if %input%==[a different number generated by %random% (example 203)] goto b
Yes, and there is no need to translate a number into a label. Simply use the random number as the label. Here is a trivial demonstration that randomly selects 1 of 5 GOTO labels:
#echo off
setlocal
set /a label=%random% %% 5
goto %label%
:0
echo random 0 abc
exit /b
:1
echo random 1 def
exit /b
:2
echo random 2 ghi
exit /b
:3
echo random 3 jkl
exit /b
:4
echo random 4 mno
exit /b
You could use the same technique to CALL a random label instead. Here is a demonstration that makes 10 random CALLs.
#echo off
setlocal enableDelayedExpansion
for /l %%N in (1 1 10) do (
set /a label=!random! %% 5
call :!label!
)
exit /b
:0
echo random 0 abc
exit /b
:1
echo random 1 def
exit /b
:2
echo random 2 ghi
exit /b
:3
echo random 3 jkl
exit /b
:4
echo random 4 mno
exit /b
--Sample output--
random 2 ghi
random 4 mno
random 3 jkl
random 2 ghi
random 2 ghi
random 3 jkl
random 1 def
random 4 mno
random 3 jkl
random 1 def
Perhaps your script has differerent contexts, and within each context you have random outcomes. Your labels can consist of a context followed by a number.
#echo off
setlocal enableDelayedExpansion
for /l %%N in (1 1 10) do (
set /a A=!random!%%5, B=!random!%%3
call :A!A!
call :B!B!
echo(
)
exit /b
:A0
echo context A random 0 abc
exit /b
:A1
echo context A random 1 def
exit /b
:A2
echo context A random 2 ghi
exit /b
:A3
echo context A random 3 jkl
exit /b
:A4
echo context A random 4 mno
exit /b
:B0
echo context B random 0 xyz
exit /b
:B1
echo context B random 1 123
exit /b
:B2
echo context B random 2 apple orange banana
exit /b
-- Sample output--
context A random 3 jkl
context B random 0 xyz
context A random 1 def
context B random 1 123
context A random 4 mno
context B random 2 apple orange banana
context A random 2 ghi
context B random 1 123
context A random 1 def
context B random 2 apple orange banana
context A random 3 jkl
context B random 2 apple orange banana
context A random 0 abc
context B random 1 123
context A random 2 ghi
context B random 1 123
context A random 2 ghi
context B random 1 123
context A random 4 mno
context B random 1 123
Yes it is possible, depending on what your view of a random spot on the batch file means. The code you provided almost works, here's an updated version:
set NUMBER=%random%
if %NUMBER%==1004 goto A
if %NUMBER%==203 goto B
:A
REM Do something
GOTO :EOF
:B
REM Do something else
You cannot jump to a random spot inside your batch file, but based on a random value, you can go to pre-defined labels. You can even define some rules where you jump to a label Z if the random value is between X and Y.
set /a number=%random% %% 5
goto destination%number%
would goto one of destination0, destination1, destination2, destination3, destination4 if that's your intent.

Use the value of the second parameter to get the fifth

I got the following code elsewhere on stackoverflow:
#echo off
rem throw the first parameter away
shift
set params=%1
:loop
shift
if [%1]==[] goto afterloop
set params=%params% %1
goto loop
:afterloop
#echo %params%
#echo on
Result: Running shifttest 1 2 3 4 5 6 7 8 yields 2 3 4 5 6 7 8
After further testing, I've discovered I can throw the first two parameters away by doing the following:
#echo off
rem throw the first two parameters away
shift
set params=%2
:loop
shift
if [%2]==[] goto afterloop
set params=%params% %2
goto loop
:afterloop
#echo %params%
#echo on
Result: Running shifttest 1 2 3 4 5 6 7 8 yields 2 3 4 5 6 7 8
I've also discovered that I can replace the %2 with %3 to throw away the first three, and so on...
My question:
Is there a way to specify how many parameters to throw away?
Example: Running shifttest 5 2 3 4 5 6 7 8 yields 6 7 8, i.e. the first parameter specifies how many parameters to throw away, including the first one.
I was thinking something along the lines of %(%1), but that obviously doesn't work.
Given this simple batch-file (test.bat), which uses a for loop to shift the command-line params %1 number of times:
#echo off
for /L %%i in (1,1,%1) do shift
echo %1 %2 %3 %4 %5 %6 %7 %8 %9
I get the following:
c:\>test 1 2 3 4 5 6 7 8 9
2 3 4 5 6 7 8 9
c:\>test 5 2 3 4 5 6 7 8 9
6 7 8 9
You could easily adapt this technique to set params to the remaining parameters. For instance:
#echo off
for /L %%i in (1,1,%1) do shift
set params=
:loop
if [%1]==[] goto afterloop
if defined params (set params=%params% %1) else (set params=%1)
shift
goto loop
:afterloop
echo %params%
Now running it yields this:
c:\>test 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
c:\>test 5 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
6 7 8 9 10 11 12 13 14 15 16 17 18
There is not a direct way to do that. This is a simple work-around:
#echo off
setlocal EnableDelayedExpansion
for /L %%i in (1,1,%1) do shift
:loop
if [%1] == [] goto afterloop
set params=%params% %1
shift
goto loop
:afterloop
echo %params%
The construct that you indicated as %(%1) would be equivalent to the following construct, if such a construct would be possible!
echo The parameter indicated by first one (the fifth): !%1
that is, expand %1 to 5 and then, with a delayed replacement. expand !5 to the fifth parameter, but this construct does not work on Batch fle parameters, just on variables. The usual way to achieve complex managements is first store the parameters in an array, and then access the array elements. For example:
#echo off
setlocal EnableDelayedExpansion
set n=0
:loop
if [%1] == [] goto afterloop
set /A n+=1
set param[%n%]=%1
shift
goto loop
:afterloop
echo The parameter indicated by first one (the fifth): !param[%param[1]%]!
#ECHO OFF
SETLOCAL
SET val=%1 %*
FOR /l %%i IN (1,1,%1) DO CALL SET "val=%%val:* =%%"
FOR /f %%j IN ("%val%") DO SET "val=%%j"
ECHO val=+%val%+
GOTO :EOF
will set val to the nth parameter when executed with thisbatch n 2 3 4 5 6 7
If n>#parameters, returns the last.
Remove the %1 in %1 %* to yield parameters numbered thisbatch n 1 2 3 4 5 6 7 (ie n=1 produces 1st after n)

Resources