Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
davep
- Posts: 24
- Joined: 29 May 2008 14:03
- Location: Nauf Kakalak
#1
Post
by davep » 03 Jun 2015 11:31
Hello batchers!
I'm trying to split a path string, and I've run into an issue where using %var% as a token value works as expected, but !var! does not:
Code: Select all
@echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set "file=E:\temp\TEST\123458--text_text1\filename.mp4"
set tokenNum=4
echo.
for /f "tokens=%tokenNum% delims=\-" %%b in ("%file%") do (
@echo.%tokenNum% = %%b
)
echo.
echo.and now with exclamation points
echo.
for /l %%n in (1,1,5) do (
set "tokenNum=%%n"
for /f "tokens=!tokenNum! delims=\-" %%b in ("%file%") do (
@echo.!tokenNum! = %%b)
)
echo.
pause
The resulting output is:
Code: Select all
C:\Users\davep\Desktop>scratch.bat
4 = 123458
and now with exclamation points
!tokenNum! delims=\-" was unexpected at this time.
!tokenNum! delims=\-" was unexpected at this time.
!tokenNum! delims=\-" was unexpected at this time.
!tokenNum! delims=\-" was unexpected at this time.
!tokenNum! delims=\-" was unexpected at this time.
Press any key to continue . . .
This is a severely reduced version of my script just to show the issue. There are a few other steps that mandate the setting of tokenNum within the loop. Long story short, I never know how deep the file is within the path, so I need to count the number of \ so I can choose the right token value to always return 123458. I can get that number fairly easily, but planting it into a for-loop using exclamation points is breaking the script.
Thank you for your time,
Dave
-
dbenham
- Expert
- Posts: 2461
- Joined: 12 Feb 2011 21:02
- Location: United States (east coast)
#2
Post
by dbenham » 03 Jun 2015 12:05
The FOR /F options are parsed prior to FOR variable expansion and delayed expansion. So you cannot use either as part of FOR /F options.
One solution is to CALL out to a subroutine, passing the values as parameters so that you can use %1 instead.
Code: Select all
for /l %%n in (1,1,5) do call :parse %%n
exit /b
:parse
for /f "tokens=%1 delims=\-" %%b in ("%file%") do echo %1 = %%b
exit /b
Dave Benham
-
davep
- Posts: 24
- Joined: 29 May 2008 14:03
- Location: Nauf Kakalak
#3
Post
by davep » 03 Jun 2015 12:16
Excellent! Thank you!
-
Ben Mar
- Posts: 22
- Joined: 03 May 2015 10:51
#4
Post
by Ben Mar » 03 Jun 2015 14:14
Another solution:
Code: Select all
@echo off
setlocal enableextensions
setlocal enabledelayedexpansion
set "file=E:\temp\TEST\123458--text_text1\filename.mp4"
set count=1
:forLoop
for /f "tokens=%count% delims=\-" %%a in ("%file%") do (
echo !count! = %%a
set /a count+=1)
if !count! lss 7 goto forLoop
)
-
Aacini
- Expert
- Posts: 1921
- Joined: 06 Dec 2011 22:15
- Location: México City, México
-
Contact:
#5
Post
by Aacini » 03 Jun 2015 14:57
... and another solution, the classical
array method that allows to store each part and later process they as you want:
Code: Select all
@echo off
setlocal enabledelayedexpansion
set "file=E:\temp\TEST\123458--text_text1\filename.mp4"
rem Separate the path in tokens
set "file2=%file:-=" "%"
set i=0
for %%a in ("%file2:\=" "%") do if %%a neq "" (
set /A i+=1
set "token[!i!]=%%~a"
)
rem Show elements of "token" array
for /l %%n in (1,1,6) do (
set "tokenNum=%%n"
for /f %%b in ("!tokenNum!") do (
@echo.!tokenNum! = !token[%%b]!
)
)
Or in a simplified form, if just one part is needed:
Code: Select all
@echo off
setlocal enabledelayedexpansion
set "file=E:\temp\TEST\123458--text_text1\filename.mp4"
set tokenNum=4
set "file2=%file:-=" "%"
set i=0
for %%a in ("%file2:\=" "%") do if %%a neq "" (
set /A i+=1
if !i! equ %tokenNum% echo %tokenNum% = %%~a
)
Antonio
-
Sponge Belly
- Posts: 233
- Joined: 01 Oct 2012 13:32
- Location: Ireland
-
Contact:
#6
Post
by Sponge Belly » 10 Aug 2015 13:22
Hello All!
Sorry I’m late to the discussion, as usual.
![Embarassed :oops:](./images/smilies/icon_redface.gif)
But my solution takes advantage of the
popping the CALL stack technique Siberia-Man told us about on June 7th:
Code: Select all
@echo off & setlocal enableextensions disabledelayedexpansion
set ^"str=^" ^&^^ ^"^^^&^"^& !^^!^^^^! %% %%OS%%^"
set "str=%str:"=""%"
call :awhile 0
set /a count-=1
echo(count is: %count%
endlocal & goto :eof
:awhile
set /a count=%1+1
(for /f eol^=^ tokens^=%count% %%A in ("%str%") do rem awhile
) && ((goto) 2>nul & call :awhile %count%)
exit /b 0
No non-terminating for /l loops, no backward-jumping gotos. Pretty nifty… if I say so myself.
- SB
-
dbenham
- Expert
- Posts: 2461
- Joined: 12 Feb 2011 21:02
- Location: United States (east coast)
#7
Post
by dbenham » 10 Aug 2015 14:06
Most of the answers have ignored the request to use a variable in FOR /F options, and instead have offered alternative ways to count the number of path nodes.
But if the goal is to simply extract the leading number from the parent folder of a file (given the full path of the file), then all you need do is use .. to get the parent folder
![Exclamation :!:](./images/smilies/icon_exclaim.gif)
There is no need to know the number of nodes.
Code: Select all
@echo off
setlocal
set "file=E:\temp\TEST\123458--text_text1\filename.mp4"
for %%F in ("%file%\..") do for /f "delims=-" %%N in ("%%~nF") do echo %%N
Dave Benham
-
davep
- Posts: 24
- Joined: 29 May 2008 14:03
- Location: Nauf Kakalak
#8
Post
by davep » 10 Aug 2015 18:08
Wonderful solution, Dave. I'll try it out asap. Thank you!