Get a variable from filename string in windows batch

842 views Asked by At

good day, i have a folder with 400 files and i want to print a "name" from the filenames this is the structure ej:

20201323223_vendo.perfil01_17872513294967257_1601950878_live.mp4
20201323223__vvcastrillon_12_17949951031375250_1601939874_live.mp4
2020323123_yessromero.g_17849208194340047_1601945592_live.mp4
2020323223_ziizii_08_17979840166310477_1601929868_live.mp4

and what i need is

vendo.perfil01
_vvcastrillon_12
yessromero.g
ziizii_08

Im try to loop in the files and separate whit the _ and extract the 2 and 3 token numeral conditioning but the result is wrong and missing variables

@echo off
setlocal EnableDelayedExpansion
:loop
SET max=5000
for /F "delims=" %%I in ('dir "*_*_*.mp4" /A-D /B /S 2^>nul ^| %SystemRoot%\System32\findstr.exe /I /L /V "\\outdir\\"') do (for /F "eol=| tokens=2,3 delims=_" %%J in ("%%~nI") do (SET "var="&for /f "delims=0123456789" %%a in ("%%K") do SET var=%%a
if defined var ( set nam=%%J_%%K ) else ( set nam=%%J )
)
echo/!nam!
)
timeout 10 > nul
goto loop

i think the answer is remove the first number before the _ then the string _xxxxxx_xxxxxxx_live.mp4 at the end but i dont know how read in reverse the tokens

tanks for any help

3

There are 3 answers

4
aschipfl On BEST ANSWER

Since you have got different numbers of _-separated items in your file names and even adjacent _, so using for /F to split them into specific tokens with delims=_ is not the best choice.

I would use a standard for-loop instead, which receives modified file names, namely with each _ replaced by " " and enclosed within "", which leads to SPACE-separated partial name items. So:

20201323223_vendo.perfil01_17872513294967257_1601950878_live.mp4

is changed to:

"20201323223" "vendo.perfil01" "17872513294967257" "1601950878" "live.mp4"

before looping. Within the loop implement an index counter and just append those items to a buffer whose index numbers lie within a certain range that depends on the total number of items.

Here is an example script that demonstrates what I mean:

@echo off
setlocal EnableExtensions DisableDelayedExpansion

rem // Define constants here:
set "_ROOT=%~dp0."           & rem // (full path to target directory)
set "_MASK=*_*_*_*_live.mp4" & rem // (pattern to match file names)
set "_FILT=^[0123456789][0123456789]*_..*_[0123456789][0123456789]*_[0123456789][0123456789]*_live\.mp4$"
                               rem // (additional `findstr` filter for file names)
set /A "_POS=1"              & rem /* (index of first `_`-separated item to extract;
                               rem     `0` is the first item, `-1` is the last) */
set /A "_NUM=-4"             & rem /* (number of `_`-separated items to extract;
                               rem     `-1` means all up to the last item) */

rem // Change into target directory:
pushd "%_ROOT%" && (
    rem // Loop through all matching non-hidden, non-system files:
    for /F "delims= eol=|" %%F in ('
        dir /B /A:-D-H-S "%_MASK%" ^| findstr /I /R /C:"%_FILT%"
    ') do (
        rem // Store current file name, initialise item index, counter and buffer:
        set "FILE=%%F" & set /A "IDX=-1, CNT=-1" & set "BUFF=_"
        rem // Toggle delayed expansion to avoid troubles with `!`:
        setlocal EnableDelayedExpansion
        rem // Count number of items and store one less:
        rem set "TEST=%FILE:_=" & set /A "CNT+=1" & set "TEST=%"
        for %%I in ("!FILE:_=" "!") do set /A "CNT+=1"
        rem // Determine item index position from given index and number:
        if !_POS! lss 0 (set /A "BEG=CNT+_POS+1") else set /A "BEG=_POS"
        if !_NUM! lss 0 (set /A "END=CNT+_NUM+1") else set /A "END=_POS+_NUM-1"
        rem // Transport numbers over `endlocal` barrier:
        for %%C in (!CNT!) do for %%B in (!BEG!) do for %%A in (!END!) do (
            rem // Loop through `_`-separated items of file name:
            for %%I in ("!FILE:_=" "!") do (
                rem // Store current item, increment item index:
                endlocal & set "ITEM=%%~I" & set /A "IDX+=1"
                setlocal EnableDelayedExpansion
                rem // Append current item to buffer if in range:
                if !IDX! geq %%B if !IDX! leq %%A (
                    rem // Transport buffer over `endlocal` barrier:
                    for /F "delims=" %%E in ("BUFF=!BUFF!_!ITEM!") do (
                        endlocal & set "%%E"
                        setlocal EnableDelayedExpansion
                    )
                )
            )
        )
        rem // Return buffer:
        echo(!BUFF:~2!
        endlocal
    )
    rem // Return from target directory:
    popd
)

endlocal
exit /B
1
Gerhard On

Something like this should help:

@echo off
setlocal enabledelayedexpansion
for /f "tokens=1* delims=_." %%i in ('dir /b /s /a-d "*_*_*.mp4"2^>nul ^| findstr.exe /ILV "\\outdir\\"') do (
    set "var=%%j"
    for /f "tokens=2,* delims=_." %%a in ("%%j") do echo !var:_%%b=!
)

Keep in mind that using delims will also split on consecutive characters like double underscore. for those you need to predetermine which has double underscore and let the script add it for you.

0
Magoo On
@ECHO OFF
SETLOCAL
for %%a in (
20201323223_vendo.perfil01_17872513294967257_1601950878_live.mp4
20201323223__vvcastrillon_12_17949951031375250_1601939874_live.mp4
2020323123_yessromero.g_17849208194340047_1601945592_live.mp4
2020323223_ziizii_08_17979840166310477_1601929868_live.mp4
) do  set "filename=%%a" &call :process&echo --------------------------------------
GOTO :EOF

:process
echo stage 1 %filename%
:: step 1 : delete all characters up to and including the first underscore
set "filename=%filename:*_=%"
echo stage 2 %filename%
:: step 2 : find all numeric strings of length 4 or more in remainder
call :strsgt4 %filename:_= %
:: step 3 : replace each numeric string of length 4 or more + preceding underscore with "/" (invalid filename character)
echo stage 3 %filename%
:proc3lp
if "%zapstrings%" neq " " for %%v in (%zapstrings%) do call set "filename=%%filename:_%%v=/%%"&call set "zapstrings=%%zapstrings: %%v=%%"&goto proc3lp 
echo stage 4 %filename%
:: step 5 : Remove all charactersincluding and after the first "/"
for /f "delims=/" %%v in ("%filename%") do echo result %%v
goto :eof

:strsgt4
set "zapstrings= "
:strsgt4loop
set "test=%1"
if not defined test goto :eof
set "test=%test:~4%"
if defined test call :isnum %test%&if not defined notnumber set "zapstrings=%zapstrings% %1"
shift
goto strsgt4loop

:: Determine whether %1 is purely numeric
:isnum
SET "notnumber=9%~1"
FOR /l %%z IN (0,1,9) DO CALL SET "notnumber=%%notnumber:%%z=%%"
GOTO :eof

Really a question of working out what your rules are.

I decided that your rules were: string after the first underscore, until before the first subsequent underscore that precedes a numeric string or length greater than 3

The %%a loop simply submits a sequence of sample strings to :process

The inline comments should explain the remainder.