2

I have code that extracts N random files from each of many sub-folders. It works fine except for files with exclamation points. I use delayed expansion, which erases the exclamation points in the 2nd for loop. If I disabled expansion at the 2nd loop then i lose the ability to use variables within variables to capture the interim results (File1, File2, File3...). Help!

@echo off
chcp 1254
REM Display N random episodes from each sub-folder in g:\itunes\podcasts
setlocal EnableDelayedExpansion
set /p COUNT=Select Desired Number of Random Episodes per Album:
REM Recurse the podcast directory
for /d %%f in (G:\itunes\Podcasts\*) do (
 set "buffer=%%f"  
  set n=0
REM http://stackoverflow.com/questions/18945521/need-to-create-a-batch-file-to-select-one-random-file-from-a-folder-and-copy-to
  for %%g in ("!buffer!\*") do (
  set /A n+=1
  set "file!n!=%%g"
)
for /l %%i in (1, 1, !COUNT!) do (
set /A "rand=(!n!*!random!)/32768+1"
REM http://stackoverflow.com/questions/9700256/bat-file-variable-contents-as-part-of-another-variable
for %%A in ("!rand!") do echo !file%%~A!
)
)
RKO
  • 161
  • 10
  • 3
    Call a sub function with `call :label parameters` inside the for loop. Then you won't need delayed expansion. –  May 19 '16 at 05:34
  • @Noodles make an answer based on your comment. However I'd use raw `call :setfile` and avoid supplying parameters. Just set variable `buffer` _before_ `call :setfile` instead. Consider calling another subroutine `:echofile` instead of last `for %%A` loop. – JosefZ May 19 '16 at 08:27
  • Alternatively, toggel delayed expansion so that it is enabled only when needed, so to be disabled when reading `for` variables like `%%i`; you need to regard that environment (variable) changes are no longer available after `endlocal`... – aschipfl May 19 '16 at 08:51
  • thanks for the responses. Noodles, what parameters should I pass when I'm actually building the parameters with set "file!n!=%%g" ... File1, File2, File3 ... – RKO May 19 '16 at 12:55
  • JosefZ, sorry I don't understand your call :setfile comment. Can you elaborate. Recall I need Expansion Enabled quite a lot (for example the Random function doesn't get reseeded without it. – RKO May 19 '16 at 12:56
  • Aschipfl, I've tried every possible combination and permutation of enabling and disabling of expansion and none of them worked .. the big issue is the exclamation points are lost at the for %%g in ("!buffer!\*") statement unless expansion is disabled at that point, but disabling it only at that point is enough to kill the ability to build the sequentially numbered filenames (File1, File2, File3...) at set "file!n!=%%g" – RKO May 19 '16 at 13:00
  • `For ... Do call :mySub %%G` and in mysub it becomes `%1` –  May 19 '16 at 20:31

1 Answers1

1

Windows batch file - Pick (up to) four random files in a folder had the right answer. I modified that solution to allow for sub-folders. The following code returns N random files from each sub-folder for a designated folder.

 @echo off
 REM Display N random episodes for each podcast folder (~20 min.)
 REM Solution Template found at: https://stackoverflow.com/questions/10978107
 chcp 1254
 setlocal disableDelayedExpansion
 set /p COUNT=Select Desired Number of Random Episodes per Album:
 REM This loop captures the subfolder names and sends them to loop1
 for /d %%f in (G:\itunes\Podcasts\* H:\itunes\Podcasts\*) do (
 set /a ind = 0
 set buffer="%%f"
 call :loop1 %buffer%
 )

 :loop1
   for /f "tokens=* delims=" %%g in ('dir %buffer% /a:-h-s-d /b /s') do (
   setlocal enableDelayedExpansion
   for %%N in (!ind!) do (
     endlocal
 REM The following dynamically creates variables, WP1, WP2 ... which are later randomized
     set "wp%%N=%%g"
   )
   set /a ind += 1
 )

 setlocal enableDelayedExpansion
 for /l %%g in (1, 1, %COUNT%) do (
   set /a "num = (((!random! & 1) * 1073741824) + (!random! * 32768) + !random!) %% %ind%"
   for %%N in (!num!) do echo !wp%%N!
 )
Community
  • 1
  • 1
RKO
  • 161
  • 10