Page 1 of 1

Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 15:14
by julesverne
My apologies in advance if this explanation is convoluted. Trying to make sure all the aspects of what I'm trying to do are understood. Variables are bolded.

What I'm trying to do:

I would like to do a for /f *.mov command to search for all .mov files named as such "Recording" in front then an unspecified number of digits then an underscore then an unspecified number of digits signifying an iteration of the filename. Examples: Recording55555_0.mov or Recording55555_12.mov Recording555_12.mov

The first .mov file the for/f finds sees if there are .flv files in the same directory that have the same file name minus the iteration (anything after the "_" ) and then ONLY if the .mov file has more than one iteration it will do a dir listing of all .flv files that match the filename regardless of iteration, otherwise if there is only one iteration of .mov file skip it. Then, when the loop continues on to the next. .mov file ignore it if the filename has been processed before regardless of iteration.

This is an example directory listing I'm working in:

Recording55555_0.mov
Recording24562_3.mov
Recording24562_4.mov
Recording24562_12.mov
Recording24562_3.flv
Recording24562_4.flv
Recording24562_12.flv
Recording55555_0.flv

so in the example directory above the for loop would find Recording24562_3.mov and then using the "if" command, since there are more than one iteration of the filename it will do a dir listing that would show Recording24562_3.flv, Recording24562_4.flv, Recording24562_12.flv
Then.. when the next loop comes around ignore Recording24562_4.mov and _12.mov (since we already have our flv listing from the first loop) but instead move onto Recording55555_0.mov. But with the if command sees that there is only one iteration of that file so it skips it.

Essentially I'm only concerned with .mov files that have more than one iteration of the same filename. But I don't want to waste time with .mov files with the same filename but different iteration if I've already processed one of them.

I figured isolating the iteration number would be key to this problem so...
Quoted below from http://ss64.com/nt/syntax-replace.html I attempted to at least remove the iterations using the ss64 method recommended below.

:: To remove characters from the right hand side of a string is
:: a two step process and requires the use of a CALL statement
:: e.g.

SET _test=The quick brown fox jumps over the lazy dog

:: To delete everything after the string 'brown'
:: first delete 'brown' and everything before it
SET _endbit=%_test:*brown=%
Echo We dont want: [%_endbit%]

::Now remove this from the original string
CALL SET _result=%%_test:%_endbit%=%%
echo %_result%


Based on that formula I've come up with this code:

Code: Select all

for %%a in (*.mov) do (
   call :getfilename %%~na
)

:getfilename

set originalfile=%~1
set iteration=%originalfile:*_=%
call set result=%%originalfile:%iteration%=%%

for /f "usebackq tokens=1 delims= " %%T in (`dir "%result%*.flv" ^| findstr File(s^)`) do (
   set /a totaliterations=%%T
)

if %totaliterations% GTR 1 dir "%result%*.flv"

goto :eof


The set iteration line accurately gives me the recording iteration as shown in the example output below.
The problem I'm getting is that the Call set is not removing the iteration from the originalfile variable, instead it is removing ALL characters that match the iteration from the variable

Example BATCH File Output

Code: Select all

D:\edit>for %a in (*.mov) do (
call :getfilename %~na
 pause
)

D:\edit>(
call :getfilename Paper24652_2
 pause
)

D:\edit>set originalfile=Recording24652_2

D:\edit>set iteration=2

D:\edit>call set result=%originalfile:2=%

D:\edit>for /F "usebackq tokens=1 delims= " %T in (`dir "Recording465_*.fbr" | findstr File(s)`) do (set /
a totaliterations=%T )


So as you can see by the time Recording24652_2 gets added to the for /f command at the bottom it has been changed to Recording4605_ . So instead of simply removing the iteration from the originalfile variable (which we get from the set iteration command and in this case is the number 2) the call set command is replacing every character with the iteration (which is not what the SS64 method says it should do).

The code above even if someone helps me figure out how to fix it, is still missing the code to skip anymore .mov files the for loop finds that match the same filename regardless of iteration.

All of that being said.. if someone has a smoother method that doesn't require calling and can all be done in a for loop. Am trying to avoid delayed expansion but I don't have to if a better method can be recommended.

edit: replaced variable names with clearer named variable names.

Thanks!!

Re: Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 19:03
by julesverne

Code: Select all

@echo on

echo. > test.txt

setlocal enabledelayedexpansion

set /a found=0
for %%a in (*.mov) do (
   for /f "usebackq delims=*" %%F in (test.txt) do (
      if %%a == %%F set /a found=1
   )
   if !found!==0 call :getfilename %%~na
   pause
   set /a found=0
)

del test.txt

exit

:getfilename

set originalfile=%~1
set iteration=%originalfile:*_=%
call set result=%%originalfile:%iteration%=%%

for /f "usebackq tokens=1 delims= " %%T in (`dir "%result%*.flv" ^| findstr File(s^)`) do (
   set /a totaliterations=%%T
)
pause
if %totaliterations% GTR 1 dir "%result%*.flv"
if %totaliterations% GTR 1 dir "%result%*.mov" >>test.txt

goto :eof


So I came up with this code to help me bypass any more files with different iterations if I've already processed a file by adding an if statement that echos dir to a text file. I ended up having to use delayedexpansion in the long run so that I could set a variable inside a for loop and have that variable be read correctly in the for loop. This still hasn't helped me to get the filename without the iteration so that I can feed it into the

Code: Select all

for /f "usebackq tokens=1 delims= " %%T in (`dir "%result%*.flv" ^| findstr File(s^)`) do (
   set /a totaliterations=%%T
)
and as a result I haven't actually tested the added if statement. Thanks to anyone who knows why I still can't get

Code: Select all

call set result=%%originalfile:%iteration%=%%
to work.

Re: Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 19:06
by Endoro
Give it a try:

Code: Select all

@ECHO OFF &SETLOCAL disableDelayedExpansion
FOR %%a IN (test\Recording*_*.mov) DO (
   FOR /f "delims=_" %%b IN ("%%~a") DO SET /a mov.%%~b+=1
)
FOR /f "tokens=1*delims==" %%a IN ('SET mov.') DO IF NOT %%b==1 (
   FOR /f "tokens=1*delims=." %%c IN ("%%~a") DO IF EXIST "%%~d_*.flv" DIR /b /a-d "%%~d_*.flv"
)


Re: Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 19:53
by julesverne
@Endoro

I tried it out and got a message I've never seen before in CMD.

Environment variable mov. not defined

Here's the output with @echo on

Code: Select all

>FOR %a IN (test/Recording*_*.mov) DO (FOR /F "delims=_" %b IN ("%~a") DO SET /a mov.%~b+=1 )

>FOR /F "tokens=1*delims==" %a IN ('SET mov.') DO IF NOT %b == 1 (FOR /F "tokens=1*delims=." %c
IN ("%~a") DO IF EXIST "%~d_*.flv" DIR /b /a-d "%~d_*.flv" )
Environment variable mov. not defined

>pause
Press any key to continue . . .


I also tried without the "test" in (test/Recording*_*.mov)

Re: Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 20:34
by julesverne
So... I figured out how to get it to do everything I needed it to albeit it is still longer code than I'd like. Endoro's slim code looks a lot more inviting although I can't get a real grasp on how to fix it or if I'm running it incorrectly. If anyone can make this code more efficient, and/or perhaps even forego having to create a temp text file would love some feedback.

@echo off
echo. > test.txt

setlocal enabledelayedexpansion

set /a found=0
for %%a in (*.mov) do (
for /f "usebackq delims=*" %%F in (test.txt) do (
if %%a == %%F set /a found=1
)
if !found!==0 call :getfilename %%~na
set /a found=0
pause
)

del test.txt

exit

:getfilename

set originalfile=%~1
set iteration=%originalfile:*_=%

call set result=%%originalfile:_%iteration%=%%
echo %result%

for /f "usebackq tokens=1 delims= " %%T in (`dir "%result%_*.flv" ^| findstr File(s^)`) do (
set /a totaliterations=%%T
)
echo !totaliterations!

if !totaliterations! GTR 1 dir /a /b "%result%_*.flv"
if !totaliterations! GTR 1 dir /a /b "%result%_*.mov" >>test.txt

goto :eof



The issue with getting the variable name without the iteration was fixed by adding in the underscore like this

Code: Select all

call set result=%%originalfile:_%iteration%=%%


Looking at it closer, what I had before was a different SS64 replace method mentioned on that same link because I omitted the underscore.

::Delete the character string 'ab'
SET _test=12345abcabc
SET _result=%_test:ab=%
ECHO %_result% =12345cc

Re: Dir Listing based on filetype and filename iteration

Posted: 23 May 2014 23:06
by foxidrive
This is Endoro's code - I just added the first bit to create the files and made it process the current folder:

It works here - run it in an empty folder.

Code: Select all

@echo off

for %%a in (
Recording55555_0.mov
Recording24562_3.mov
Recording24562_4.mov
Recording24562_12.mov
Recording24562_3.flv
Recording24562_4.flv
Recording24562_12.flv
Recording55555_0.flv
) do break>%%a

@ECHO OFF &SETLOCAL disableDelayedExpansion
FOR %%a IN (Recording*_*.mov) DO (
   FOR /f "delims=_" %%b IN ("%%~a") DO SET /a mov.%%~b+=1
)
FOR /f "tokens=1*delims==" %%a IN ('SET mov.') DO IF NOT %%b==1 (
   FOR /f "tokens=1*delims=." %%c IN ("%%~a") DO IF EXIST "%%~d_*.flv" DIR /b /a-d "%%~d_*.flv"
)
pause

Re: Dir Listing based on filetype and filename iteration

Posted: 24 May 2014 12:03
by julesverne
foxidrive wrote:This is Endoro's code - I just added the first bit to create the files and made it process the current folder:

It works here - run it in an empty folder.

Code: Select all

@echo off

for %%a in (
Recording55555_0.mov
Recording24562_3.mov
Recording24562_4.mov
Recording24562_12.mov
Recording24562_3.flv
Recording24562_4.flv
Recording24562_12.flv
Recording55555_0.flv
) do break>%%a

@ECHO OFF &SETLOCAL disableDelayedExpansion
FOR %%a IN (Recording*_*.mov) DO (
   FOR /f "delims=_" %%b IN ("%%~a") DO SET /a mov.%%~b+=1
)
FOR /f "tokens=1*delims==" %%a IN ('SET mov.') DO IF NOT %%b==1 (
   FOR /f "tokens=1*delims=." %%c IN ("%%~a") DO IF EXIST "%%~d_*.flv" DIR /b /a-d "%%~d_*.flv"
)
pause


yup... totally works now. Have no idea what.. no idea. Thanks @endoro @foxidrive I always feel like I'm pretty good at this stuff and then I see the stuff you guys come up with and my mind gets blown. Never thought of using SET command as the parameter in a for loop. I don't really get it. Honestly.. it is going to take me awhile to really understand what is happening in that code. I will eventually figure it out but for now I'm just going to put my eyes back in my head and continue on. Thanks again!