Help to optimize the batch script

I have a directory with fonts, say C:\fonts Inside the directory there are others directories where the fonts are sorted alphabetically, like A B C D .. Z. What I want to do with the batch is to copy fonts randomly from the different directories A-Z to the system fonts directory (%systemroot\fonts). I want to be able to specify a range number of fonts that batch script will be copying, like from 20 to 30 as example. Current script do the work, except it copies just 30 fonts. Also, my biggest problem is...the script is quite slow to do the copy. I was wondering if it's possible to optimize it somehow for a faster work???!!!
Here is the script:

@echo off
setlocal EnableExtensions EnableDelayedExpansion

:loop

pushd "F:\fonts"

set "xCount=0"
for /f %%A in ('dir *.* /a:-d /s ^| find "File(s)"') do set "xCount=%%~A"

set /a "xIndex=%Random% %% %xCount%"

set "xTally=0"
for /f "delims=" %%A in ('dir *.* /a:-d /b /s') do (
    if "!xTally!" EQU "%xIndex%" (
        xcopy "%%~fA" "%systemroot%\fonts" /Y
        goto End
    )
    set /a "xTally+=1"
)

:End
popd

set /a executecounter=%executecounter%+1
if "%executecounter%"=="30" goto done
goto loop
:done

endlocal
DarylPhillipsryAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

QlemoBatchelor, Developer and EE Topic AdvisorCommented:
Of course that batch is slow, because you are going thru the folder list twice for each go, and that 30 times. The count of files found will not change, so it is sufficient to get that only once, outside of the loop.

Further, if you need 30 out of x files, it is sufficient to "roll a dice" each time while going thru the files, you do not need to start all over again each time.
I would just check for %random% being greater than half of its value range (0 to 32767 = 32768 values => 16384 values in first half), and then copy, until 30 files are copied. Not exact maths, since it prefers files from the start of the algorithm, but sufficient.

If my maths are correct, the exact algorithm is
   chunk = maxrandom / desiredFileCount
   if random mod chunk = 0 then copy
@echo off
setlocal EnableExtensions EnableDelayedExpansion

pushd "F:\fonts"

set cnt=0
set maxcnt=30

for /f %%A in ('dir *.* /a:-d /s ^| find "File(s)"') do set /a chunk= 32768 / %%~A

:Loop
for /f "delims=" %%A in ('dir *.* /a:-d /b /s') do (
    set /a rnd= !random! mod %chunk%
    if !rnd! equ 0 (
        copy "%%~fA" "%systemroot%\fonts\" /Y
        set /a cnt += 1
    )
    if !cnt! geq %maxcnt% goto End
)
if %cnt% lss %maxcnt% goto Loop

:End
popd

endlocal

Open in new window

0
oBdACommented:
This one creates an indexed list first; will not copy the same font twice. It's in test mode and will only display the copy commands it would normally run. Remove the uppercase ECHO in line 28 to run it for real:
@echo off
setlocal enabledelayedexpansion
set RootDir=F:\Fonts
set Mask=*.ttf
set TargetDir=%systemroot%\fonts
set /a CopyCount=30

set /a FileCount = 0
echo Collecting fonts ...
for /f "delims=" %%a in ('dir /s /b "%RootDir%\%Mask%"') do (
	echo - %%~nxa
	set /a FileCount += 1
	set File[!FileCount!]=%%a
)
if %FileCount% lss %CopyCount% (
	echo Error: Supposed to copy %CopyCount% files, but found only %FileCount%.
	pause
	exit /b 1
)

echo Found %FileCount% fonts, will select %CopyCount% at random.
set /a LoopCount = 0
:LoopSelect
set /a Index = %Random% %% FileCount + 1
if not defined File[%Index%] goto LoopSelect
set /a LoopCount += 1
echo [%LoopCount%/%CopyCount%] Copying '!File[%Index%]!' ...
ECHO copy "!File[%Index%]!" "%TargetDir%"
set File[%Index%]=
if %LoopCount% lss %CopyCount% goto LoopSelect

Open in new window

0
DarylPhillipsryAuthor Commented:
The script seems fixing the slow loop problem, but how I can set a random number of fonts to copy?
Say I don't need to copy 30 fonts everytime, but from 20 to 40.
0
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

oBdACommented:
@echo off
setlocal enabledelayedexpansion
set RootDir=C:\Temp
set Mask=*.ttf
set TargetDir=%systemroot%\fonts
set /a CopyRangeMin=20
set /a CopyRangeMax=40

set /a CopyCount = (%Random% %% (CopyRangeMax - CopyRangeMin + 1)) + CopyRangeMin
set /a FileCount = 0
echo Collecting fonts ...
for /f "delims=" %%a in ('dir /s /b "%RootDir%\%Mask%"') do (
	echo - %%~nxa
	set /a FileCount += 1
	set File[!FileCount!]=%%a
)
if %FileCount% lss %CopyCount% (
	echo Error: Supposed to copy %CopyCount% files, but found only %FileCount%.
	pause
	exit /b 1
)

echo Found %FileCount% fonts, will select %CopyCount% at random.
set /a LoopCount = 0
:LoopSelect
set /a Index = %Random% %% FileCount + 1
if not defined File[%Index%] goto LoopSelect
set /a LoopCount += 1
echo [%LoopCount%/%CopyCount%] Copying '!File[%Index%]!' ...
ECHO copy "!File[%Index%]!" "%TargetDir%"
set File[%Index%]=
if %LoopCount% lss %CopyCount% goto LoopSelect

Open in new window

0
DarylPhillipsryAuthor Commented:
Collecting fonts ...
The system cannot find the file specified.
Error: Supposed to copy 23 files, but found only 0.

something wrong with the script :/
0
oBdACommented:
Sorry, forgot to change the RootDir back to F:\Fonts; did you change line 3 accordingly?
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
DarylPhillipsryAuthor Commented:
This is high quality job.  A+++
Thanks
0
DarylPhillipsryAuthor Commented:
This is high quality job.  A+++
Thanks
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Windows Batch

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.