As the title says, I'm trying to pick up to four random files (wallpapers) from a folder, for further processing. The folder does not contain subfolders, just *.jpg's, *.bmp's and *.png's (it may contain a Thumbs.db file, but I already took care of that).
I read all the files with a for loop making something similar to an array, then I'd like to run another for loop for making the random numbers that will act as indexes for choosing the files.
setlocal enabledelayedexpansion
set "wps=1 2 3 4"
set /a ind = 0
for /f "tokens=* delims=" %%g in ('dir C:\Wallpapers /a:-h-s /b /s') do (
set /a ind += 1
set "!ind!=%%g"
)
for %%g in (%wps%) do (
set /a "num = (((!random! & 1) * 1073741824) + (!random! * 32768) + !random!) %% %ind% + 1"
echo Wallpaper %%g is #!num! - Title: "!!num!!"
)
Of course the line that echoes just outputs Wallpaper 1 is #118 - Title: "118" instead of Wallpaper 1 is #118 - Title: "C:\Wallpapers\Miami Skyline.jpg".
So my specific question is: how can I double expand a variable inside a for loop?
[Note #1: the line that creates the random number needs to be so long because it gives a good random distribution of values]
[Note #2: I need wps to be stored that way, because sometimes I could need just three wallpapers, not necessarily in numerical order]
Transfer the !num! value to a FOR variable :-)
for %%N in (!num!) do echo Wallpaper %%g is #%%N - Title: "!%%N!"
A few additional pointers:
As written, your DIR command is including folders. You need to add the /A-D option
dir C:\Wallpapers /a:-h-s-d /b /s
Your numeric variable names work in your existing code. But you will have fits if you ever try to access them using normal expansion because %1% will expand as the 1st batch argument instead of the environment variable. In general practice you should avoid beginning an environment variable with a number. You could use:
set wp!ind!=%%g
...
echo Wallpaper %%g is #!num! - Title: "!wp%%N!
You can make your array 0 based by incrementing your counter at the bottom of the loop instead of the top. Then you don't need to add one to your random number. (This tip is trivial. More a matter of style.)
You don't need both "tokens=*" and "delims=". I recommend the latter. "delims=" will keep the entire string. tokens=* will keep the entire string after it strips leading spaces and tabs. A file name can begin with spaces.
Your code will fail if any of the file names contain ! characters. The exclamation will be corrupted during expansion of %%g because of delayed expansion. It is fairly easy to fix by toggling delayed expansion on and of and using a FOR variable to transfer the value across the ENDLOCAL barrier.
Here is the code with all of the recommendations in place
#echo off
setlocal disableDelayedExpansion
set "wps=1 2 3 4"
set /a ind = 0
for /f "tokens=* delims=" %%g in ('dir C:\Wallpapers /a:-h-s-d /b /s') do (
setlocal enableDelayedExpansion
for %%N in (!ind!) do (
endlocal
set "wp%%N=%%g"
)
set /a ind += 1
)
setlocal enableDelayedExpansion
for %%g in (%wps%) do (
set /a "num = (((!random! & 1) * 1073741824) + (!random! * 32768) + !random!) %% %ind%"
for %%N in (!num!) do echo Wallpaper %%g is #%%N - Title: "!wp%%N!"
)
You could use another FOR like dbenham suggested or you could use CALL
call echo Wallpaper %%g is #!num! - Title: "%%!num!%%"
A CALL expands a line a second time, but only the percent expansion, neither delayed nor FOR-loop expansion works in the second reparse of the line.
EDIT: This only works, if the content of num doesn't begin with a number.
But you could use cmd /c to expand a second time, then it works also with numeric names.
cmd /c echo Wallpaper %%g is #!num! - Title: "%%!num!%%"
Related
I have the following which pares down a folder name (FOLDER) to only all text preceding the first space (tmpFOLDER).
#echo off
setlocal EnableExtensions DisableDelayedExpansion
pushd "%~dp0" || exit /B
for %%I in (..) do set "FOLDER=%%~nxI"
for /f "tokens=1 delims= " %%a in ("%FOLDER%") do set tmpFOLDER=%%a
ECHO %FOLDER%
ECHO %tmpFOLDER%
popd
endlocal
PRIMARY REQUEST:
Is there a way to do this in reverse?
Folder name (%FOLDER%): Smith - John
Example current (%tmpFOLDER%): Smith
Example desired (%tmpFOLDER%): John
SECONDARY:
Is there a way to do this with files, as well, disregarding any filetypes (ie. .txt)?
File name (%FILE%): "Smith - John.txt"
Example current (%tmpFILE%): Smith
Example desired (%tmpFILE%): John
The for /F loop cannot extract tokens counted from the end of a string. However, you could use a standard for loop that walks through the words of the file or directory names:
#echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Retrieve base name of grand-parent directory of this script:
for /D %%I in ("%~dp0..") do set "FOLDER=%%~nI"
echo Old name: "%FOLDER%"
set "PREV=" & set "COLL="
rem /* Unnecessary loop iterating once and returning the whole directory name;
rem it is just here to demonstrate how to handle also more than one names: */
for /F "delims= eol=|" %%L in ("%FOLDER%") do (
rem // Store current name strng and reset some interim variables:
set "NAME=%%L" & set "PREV=" & set "COLL= "
rem // Toggle delayed expansion to avoid issues with `!` and `^`:
setlocal EnableDelayedExpansion
rem // Ensure to have each space-separated word quoted, then loop through them:
for %%K in ("!NAME: =" "!") do (
rem /* Build new buffer by concatenating word from previous loop iteration,
rem then transfer it over `endlocal` barrier (localised environment): */
for %%J in ("!COLL! !PREV!") do (
rem // Store current word in an unquoted manner:
endlocal & set "ITEM=%%~K"
rem // Store current buffer, store current word for next iteration:
set "COLL=%%~J" & set "PREV=%%~K"
setlocal EnableDelayedExpansion
)
)
endlocal
)
rem // Retrieve final result:
set "RESULT=%COLL:~3%"
echo New name: "%RESULT%"
echo Last word: "%PREV%"
endlocal
exit /B
This approach returns the name with the last word removed as well as the last word of the name.
An alternative solution is the sometimes so-called code injection technique, which requires delayed variable expansion and is quite hard to understand:
setlocal EnableDelayedExpansion
echo Old name: "%FOLDER%"
set "RESULT=%FOLDER: =" & set "RESULT=!RESULT!!ITEM!" & set "ITEM= %"
echo New name: "%RESULT%"
echo Last word: "%ITEM:* =%"
endlocal
Note, that this will fail when the input string contains !, ^ or " (but the latter cannot occur in file or directory names anyway).
Yet another method is to replace spaces by \ and then to (mis-)use the ~-modifiers, which works because a pure file or directory name cannot contain \ on its own:
echo Old name: "%FOLDER%"
rem // Precede `\` to make pseudo-path relative to root, then replace each ` ` by `\`:
for %%I in ("\%FOLDER: =\%") do (
rem // Let `for` meta-variable expansion do the job:
set "RESULT=%%~pI"
set "LAST=%%~nxI"
)
rem // Remove leading and trailing `\`; then revert replacement of ` ` by `\`:
set "RESULT=%RESULT:~1,-1%"
echo New name: "%RESULT:\= %"
echo Last word: "%LAST%"
This approach does not even require delayed expansion.
My code is
FOR /F "skip=1 tokens=1-6" %%G IN ('WMIC Path Win32_LocalTime Get Day^,Hour^,Minute^,Month^,Second^,Year /Format:table') DO (
IF "%%~L"== "" goto s_done
Set _yyyy=%%L
Set _mm=00%%J
Set /a _nextmm=_mm+1
)
:s_done
What I want is this variable "_nextmm" = this variable "_mm" + 1
But when I run this code. It's result is
IF "2021" == "" goto s_done
Set _yyyy = 2021
Set _mm = 008
Set /a _nextmm = _mm+1
And I call echo %_nextmm%. The result is 1 instead of 009.
What did I do wrong in here?
I hope there are no SPACEs around the equal-to signs in your actual set command lines as they would harm. The best way is this syntax:
rem /* No spaces around `=`-sign, and quotes around the whole assignment expression,
rem which avoids unwanted training whitepsaces and protects special characters;
rem without assigning the quotes themselves to the variable value: */
set "VAR=Value"
Anyway, use:
set /A "_nextmm=%%J+1"
instead of set /A _nextmm=_mm+1, because (as I assume) %%J is 8, which is a correct decimal number, but _mm is 008, which is treated as an octal number due to the leading zeros (yes, I know, this is not intuitive, but take a look at this), which is invalid as there are only digits 0 to 7, hence 0 is taken for further arithmetic operations.
If you have your echo command line within the body of the for /F loop (so before the closing )), use:
for /F … (
…
call echo %%_nextmm%%
)
or use delayed variable expansion:
setlocal EnableDelayedExpansion
for /F … (
…
echo !_nextmm!
)
endlocal
If you have your echo command line outside of the body of the for /F loop (so after the closing )), normal or immediate expansion will work as expected:
for /F … (
…
)
echo %_nextmm%
TBH, I'm not sure of your logic, because if this was done in December 2021, then adding 1 would make the month incorrectly 13, and the year would remain as 2021.
For that reason, it would be much better if you just used PowerShell to assist you instead of WMIC. PowerShell sees dates as objects not strings, so you can perform the math directly in order to define the required values for your variables.
For /F "Tokens=1-2" %%G In ('
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile
-Command "(Get-Date).AddMonths(1).ToString('yyyy MM')"') Do (Set "_yyyy=%%G"
Set "_MM=%%H")
If you wanted to do it without splitting the line up for better reading then:
For /F "Tokens=1-2" %%G In ('%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -Command "(Get-Date).AddMonths(1).ToString('yyyy MM')"') Do Set "_yyyy=%%G" & Set "_MM=%%H"
So what I'm trying to do is create a find for multiple people where it in the text file it will say names and numbers like
Example of text file:
Beth
1234567891
Jay
2134456544
This is the best way I can explain what I'm trying to do:
#echo off
set "file=Test1.txt"
setlocal EnableDelayedExpansion
<"!file!" (
for /f %%i in ('type "!file!" ^| find /c /v ""') do set /a n=%%i && for /l %%j in (1 1 %%i) do (
set /p "line_%%j="
)
)
set /a Name=1
set /a Number=2
Echo Line_%Name%> %Name%.txt (Im trying to get this to say line_2 to say 1st line in the text file)
Echo Line_%Number%> %Name%.txt (Im trying to get this to say line_2 to say 2nd line in the text file)
:Start
set /a Name=%Name%+2 (These are meant to take off after 1 so lines 3,5,7,9 so on)
set /a Number=%Number%+2 (These are meant to take off after 2 so lines 4,6,8,10 so on)
Echo Line_%Name%
Echo Line_%Number%
GOTO :Start
so the outcome would be
In Beth.txt:
Beth
1234567891
So every name will be a file name and the first line in a file. I will change it later so I can do a addition in each text file.
Name: Beth
Number: 1234567891
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
SET "sourcedir=u:\your files"
SET "destdir=u:\your results"
SET "filename1=%sourcedir%\q65417881.txt"
rem make sure arrays are empty
For %%b IN (name number) DO FOR /F "delims==" %%a In ('set %%b[ 2^>Nul') DO SET "%%a="
rem Initialise counter and entry array
SET /a count=0
SET "number[0]=dummy"
FOR /f "usebackqdelims=" %%a IN ("%filename1%") DO (
IF DEFINED number[!count!] (SET /a count+=1&SET "name[!count!]=%%a") ELSE (SET "number[!count!]=%%a")
)
rem clear out dummy entry
SET "number[0]=dummy"
FOR /L %%c IN (1,1,%count%) DO (
rem replace spaces with dashes
SET "name[%%c]=!name[%%c]: =-!"
rem report to console rem report to console
ECHO Name: !name[%%c]! Number: !number[%%c]!
rem generate name.txt file
(
ECHO !name[%%c]!
ECHO !number[%%c]!
)>"%destdir%\!name[%%c]!.txt"
)
GOTO :EOF
You would need to change the values assigned to sourcedir and destdir to suit your circumstances. The listing uses a setting that suits my system.
I deliberately include spaces in names to ensure that the spaces are processed correctly.
I used a file named q65417881.txt containing your data for my testing.
The line data read from the file is assigned to %%a is assigned to and number[!count!] alternately. The data is retained in these arrays for use by further processing.
[Edited to include conversion of spaces within names to dashes]
If I understand correctly, you want to precede every second line with Number: + SPACE and every other line with Name: + SPACE. For this you do not need to store each line in a variable first, you can use a single for /F loop lo read the file line by line and process every line individually. There are two possibilities:
Temporarily precede every line with a line number plus : using findstr /N:
#echo off
rem // Loop through lines and precede each with line number plus `:`:
for /F "tokens=1* delims=:" %%K in ('findstr /N "^" "Test1.txt"') do (
rem // Calculate remainder of division by two:
set /A "MOD=%%K%%2" 2> nul
rem // Toggle delayed expansion to avoid issues with `!`:
setlocal EnableDelayedExpansion
rem // Conditionally return line string with adequate prefix:
if !MOD! neq 0 (
endlocal & echo Name: %%L
) else (
endlocal & echo Number: %%L
)
)
This will fail when a line begins with the a :.
Check whether numeric representation of current line string is greater than 0:
#echo off
rem // Loop through (non-empty) lines:
for /F "usebackq delims=" %%L in ("Test1.txt") do (
rem // Determine numeric representation of current line string:
set /A "NUM=%%L" 2> nul
rem // Toggle delayed expansion to avoid issues with `!`:
setlocal EnableDelayedExpansion
rem // Conditionally return line string with adequate prefix:
if !NUM! equ 0 (
endlocal & echo Name: %%L
) else (
endlocal & echo Number: %%L
)
)
This fails when a name begins with numerals and/or when a numeric line is 0.
And just for the sake of posting something different:
#SetLocal EnableExtensions DisableDelayedExpansion & (Set LF=^
% 0x0A %
) & For /F %%G In ('Copy /Z "%~f0" NUL') Do #Set "CR=%%G"
#For /F "Tokens=1,2* Delims=:" %%G In ('%__AppDir__%cmd.exe /D/V/C ^
"%__AppDir__%findstr.exe /NR "^[a-Z]*!CR!!LF![0123456789]" "Test1?.txt" 2>NUL"
') Do #(SetLocal EnableDelayedExpansion
(Set /P "=Name: %%I!CR!!LF!Number: " 0<NUL & Set "_="
For /F Delims^=^ EOL^= %%J In ('%__AppDir__%more.com +%%H "%%G"') Do #(
If Not Defined _ Set "_=_" & Echo %%J)) 1>"%%I.txt" & EndLocal)
This file should be run with the Test1.txt file in the current working directory. It is important that along side Test1.txt, there are no other .txt files with the same basename followed by one other character, (for example Test1a.txt or Test12.txt). Should you wish to change your filename, just remember that you must suffix its basename in the above code with a ? character, (e.g. MyTextFile.log ⇒ MyTextFile?.log).
I had the rare opportunity to verify that this script worked against the following example Test1.txt file:
Beth
1234567891
Jay
2134456544
Bob
2137856514
Jimmy
4574459540
Mary
3734756547
Gemma
6938456114
Albert
0134056504
I need a way to use batch to look at every line of a text file, and delete half of the lines in that text file, choosing which lines to delete at random.
This is to simulate a tournament within a game of D&D. All I need is a way to crunch out the winners of each tourney round. I can easily make a batch file that copies the text file and renames it for each round, but it's the reduce by half part that I'm not good with.
Edit: I want a batch file to do this because it would take way to much time to do by hand at the table. Also the game's very old and roleplay focused, so there is an actual list of NPC characters in the tourney and the PCs will want to know how their friends fared in the competition.
The design specified in the question is flawed. You cannot randomly delete half the lines because then for any given game, you might end up with 2 winners, or no winners. The input file must have a structure that specifies which contestants play each other, and then a winner must be randomly selected from each contest.
The solution below assumes each line represents a player, and for each round, line 1 plays line 2, line 3 plays line 4, etc. The number of lines must always be a power of 2 >=2 (2, 4, 8, 16, 32, 64, ...)
#echo off
setlocal enableDelayedExpansion
set "file=tournament.txt"
for /f %%C in ('find /c /v "" ^<"%file%"') do (
for /l %%N in (1 2 %%C) do (
set /p "p1="
set /p "p2="
set /a "1/(!random!%%2)" 2>nul&&echo !p1!||echo !p2!
)
) <"%file%" >"%file%.new"
move /y "%file%.new" "%file%" >nul
The outer loop counts the number of lines. The inner loop counts the odd numbers from 1 to the count, so it iterates exactly (line count divided by 2) times. The inner loop has input redirected to the source file, and the output redirected to a temporary file.
Each inner loop iteration represents a game in the tournament. SET /P is used to load the player names into variables. Then 1 is divided by a random number modulo 2, which will result in a divide by 0 error 50% of the time. The error message is redirected to nul, and then conditional operators are used to print one or the other player to the output file.
Upon completion of the loop, the temporary file is moved to replace the original file.
This method preserve the order of original lines.
#echo off
setlocal EnableDelayedExpansion
rem Generate an array of line numbers with all file lines
for /F "delims=:" %%a in ('findstr /N "^" input.txt') do (
set "n[%%a]=%%a"
set "lines=%%a"
)
rem Delete half the numbers in the array in random order
set /A halfLines=lines/2
for /L %%n in (%lines%,-1,%halfLines%) do (
set /A rnd=!random!*%%n/32768+1
set /A n[!rnd!]=n[%%n]
set "n[%%n]="
)
rem Reorder the resulting elements
for /F "tokens=2,3 delims=[]=" %%i in ('set n[') do (
set "l[%%j]=1"
set "n[%%i]="
)
rem Copy such lines
(for /F "tokens=1* delims=:" %%a in ('findstr /N "^" input.txt') do (
if defined l[%%a] (
echo(%%b
set "l[%%a]="
)
)) > output.txt
#echo off
setlocal enableextensions disabledelayedexpansion
set "inputFile=list.txt"
set "outputFile=remaining.txt"
set "odd=1"
>"%outputFile%" (
for /f "tokens=1,* delims=¬" %%a in ('
"cmd /q /v /e /c"
for /f "usebackq delims=" %%l in ("%inputFile%"^) do (
set /a 100000000+%random%*^!random^!^&echo(¬%%l
^)
""
^| sort /+3
') do if not defined odd ( set "odd=1" ) else (
echo %%b
set "odd="
)
)
type "%outputFile%"
This will take the input file, for each line echo its contents with a random prefix, sort this list using the random number as key and from this list echo only odd lines to output file.
edited I've seen the Aacini's answer and, yes, it can be useful to have the output in the same order than the input. If this is the case, just to have another version
#echo off
setlocal enableextensions disabledelayedexpansion
set "inputFile=list.txt"
set "outputFile=remaining.txt"
setlocal enabledelayedexpansion
rem Retrieve and calculate line limits to process
for /f %%a in ('^<"!inputFile!" find /c /v ""') do set /a "nLines=%%a", "nLimit=%%a/2"
rem Prepare an array with shuffled line numbers
for /l %%a in (1 1 %nlines%) do (
set /a "sel=!random! %% %%a + 1"
if !sel!==%%a ( set "r[%%a]=%%a" ) else (
for %%s in (!sel!) do set /a "r[%%a]=!r[%%s]!", "r[%%s]=%%a"
)
)
rem Read input file and output selected lines
<"!inputFile!" >"!outputFile!" (
for /l %%a in (1 1 %nLines%) do (
set /p "line=" || set "line="
if !r[%%a]! leq %nLimit% echo(!line!
)
)
type "!outputFile!"
This is a native Windows batch script using Jscript to randomise the lines of a text file and print half of them.
The size of the file is limited to the RAM that Jscript is able to request.
#if (#X)==(#Y) #end /* harmless hybrid line that begins a JScript comment
:batch file portion
#echo off
if "%~1"=="" (
echo(Purpose: Randomises a text file - prints every 2nd random line
echo(
echo(Syntax: "%~0" "inputfile.txt" ^> "outputfile.txt"
echo(
pause
goto :EOF
)
:: Randomises a file
::
:: Reads the lines of file %1 into a jscript sparse array
:: with a random number and space before each line.
:: The array is sorted using the random numbers,
:: and the randomised lines are printed - prints every 2nd random line
#echo off
cscript //E:JScript //nologo "%~f0" %*
:pause
exit /b
************ JScript portion ***********/
e=0;
var array = new Array();
fso = new ActiveXObject("Scripting.FileSystemObject");
input=fso.OpenTextFile((WScript.Arguments(0)),1);
while (!input.AtEndOfStream) {
array[e]=Math.random()+" "+input.ReadLine();
e++;
}
input.close();
array.sort();
var re = new RegExp(".*? (.*)");
c=0;
while (c<e) {
var arr = re.exec(array[c])
if (c % 2) WScript.StdOut.Writeline(RegExp.$1);
c++;
}
Including a PowerShell solution for completeness.
$lines = Get-Content input.txt
$lines | foreach { $i=0 } {
[PSCustomObject]#{index=$i;line=$_}
$i++
} |
Get-Random -count ($lines.length / 2) |
sort index |
select -Expand line |
Set-Content output.txt
This reads the input file, and builds an array of custom objects associating the text with its line number. The script uses Get-Random to select half the lines. Get-Random does not preserve order, so the script then sorts on the original line number. It then extracts the original lines in order and writes them out.
This script above requires PowerShell 3.0 for the PSCustomObject. Version 3.0 comes preinstalled on Windows 7 and above. If you need to run on Vista, you can use PSObject instead, as shown in this answer or this blog post.
Note that if the line order doesn't matter, then this script becomes much simpler.
$lines = Get-Content input.txt
$lines | Get-Random -count ($lines.length / 2) | Set-Content output.txt
To run a PowerShell script from a batch file or the CMD prompt, use the following.
powershell.exe -ex bypass -file yourscript.ps1
Or if your script fits entirely in one line, no need to create a separate ps1
powershell.exe -c "$l = gc input.txt; $l | Get-Random -c ($l.length / 2) | sc output.txt"
One way to do this would be to create simple files for each character. Then use a random script to do something like this:
set/a number=%random% * (number of people there are) / 32768 + 1
set status=dead
call person%number%.bat (Each file should contain a set status=live script)
if %status% == live (
set/a peopletokill=%peopletokill%-1
del person%number%.bat
)
if %peopletokill% == 0 (
exit
)
Something like that could work.
Hi I do need to extract the last part of a string after the last dot
Example:
1.2.37 ==> I need the 37
1.2.567 ==> I need the 567
as you can see the number of characters after the dot is not fixed so expressions like
base=%fullver:~0,-2%
Can't be used. How can I achieve this?
#echo off
setlocal enableextensions disabledelayedexpansion
set "fullver=1.2.456"
for %%a in ("%fullver:.=\%") do set "base=%%~na"
echo %base%
The trick is to replace the dots with backslashes, process the string as a path and retrieve the name of the last element in it.
Alternatively, if all the elements need to be retrieved, instead of a for, a for /f is used to tokenize the variable using the dots as separators
#echo off
setlocal enableextensions disabledelayedexpansion
set "fullver=1.2.456"
for /f "tokens=1-3 delims=." %%a in ("%fullver%") do (
set "major=%%a"
set "minor=%%b"
set "build=%%c"
)
echo [%major%] [%minor%] [%build%]
I found the following question which actually tokenizes the string.
How to split a string in a Windows batch file?
May be you can try using this to delimit it with "." and take the last value stored in the string variable. Not sure if there is a simple way, but this works.
Here is an edited Version to fit your Needs:
#echo off
setlocal ENABLEDELAYEDEXPANSION
REM Set a string with an arbitrary number of substrings separated by semi colons
set teststring=1.2.5.234
for /f "tokens=1 delims=." %%a IN ("!teststring!") DO set firststring=%%a
echo !firststring!
REM Do something with each substring
:stringLOOP
REM Stop when the string is empty
if "!teststring!" EQU "" goto END
for /f "delims=." %%a in ("!teststring!") do set substring=%%a
REM Now strip off the leading substring
:striploop
set stripchar=!teststring:~0,1!
set teststring=!teststring:~1!
if "!teststring!" EQU "" goto stringloop
if "!stripchar!" NEQ "." goto striploop
goto stringloop
:END
echo !substring!
endlocal
I prefer MC ND's answer if you are looking for only the last node, or if you know how many nodes there are.
Here is a method to capture all nodes if the total number of nodes is unknown:
#echo off
setlocal enableDelayedExpansion
set "fullver=1.2.456"
:: Parse each node and store in an "array"
set cnt=0
for %%A in (%fullver:.= %) do (
set /a cnt+=1
set "node.!cnt!=%%A"
)
:: Show the results
for /l %%N in (1 1 %cnt%) do echo node.%%N = !node.%%N!
Another solution! This one gets the first and last parts of the string:
#echo off
setlocal
set "testString=1.2.5.234"
set "first="
for %%a in ("%testString:.=" "%") do (
if not defined first set "first=%%~a"
set "last=%%~a"
)
echo First: %first%
echo Last: %last%
As a bonus, this method correctly process special Batch characters that may appear in the string, excepting wild-cards.
You can use the below command to achieve what you want.
base=%fullver:~~4,3%
4 implies 4th digit i.e., 5 and 3 implies 3 digits from 4.
The output will be
567