Случайный перебор по списку без повторения
Прошу помощи в оптимизации скрипта. Цель - выбрать все файлы из вложенных папок, подходящие под определённое условие (черный список\белый список) и запустить их в случайном порядке без повторений. В принципе задача довольно простая, и мною за десять минут был набросан приведённый ниже скрипт. Оттестировал на домашнем компьютере с папкой в пару сотен файлов, всё отлично работает. Но после запуска на довольно слабом по современным меркам компьютере и объеме файлов в ~16 тысяч столкнулся с заметными подвисаниями в пару десятков секунд перед переходом к следующему файлу. Собственно, проблема в функции :RebuildArray, которая каждый раз при запуске случайного файла, удаляет его из массива, генерируемого при старте скрипта. Думал над тем, как её ускорить - ничего не приходит в голову. Нужен именно батник, использование perl\python\чего-нибудь ещё - невозможно.
Код:
@Echo Off
SetLocal EnableDelayedExpansion
::========Настройки========
:: Путь к рабочей директории, будут обработаны все файлы и поддиректории в ней
Set BasePath=D:\Video\MLP
:: Черный список - всё, что здесь перечислено, исключается из обработки.
:: Проверяются пути и имена файлов или их части, каждое значение должно быть заключено в кавычки.
Set BlackList=".ass" ".srt"
:: Белый список - действует аналогично черному списку, но в обработку попадает лишь перечисленное.
:: Белый список применяется ДО черного, но не отменяет его действие
Set WhiteList="Season_1" "Season_2" "Season_3"
:Main
:: Запуск в случайном порядке без повторений всех найденных файлов (ассоциированной с этим файлом программой)
Call :MakeArray||(Echo ERROR: No files found&Exit /B 1)
For /L %%? In (1,1,%ArraySize%) Do (
Call :GetRandomElement||(Echo ERROR: No more files in the queue&Exit /B 1)
Call Set "File=%%Array[!Selected!]%%"
:: Вывод сообщения и запуск файла, переход на следующий после подтверждения
CLS
For /F "delims=" %%F In ("!File!") Do (
Echo.
Echo Location: %%~dpF
Echo File: %%~nxF
Echo.
)
Start "" "!File!"
Echo Press any key to next file [%%?/%ArraySize%]
Pause>nul
Call :RebuildArray
)
Exit /B
:MakeArray
:: Создаём массив из подходящих под условия файлов
Set ArraySize=0
:: Подготовка к работе черного и белого списков
For %%? In (Include Exclude) Do (Set %%?=)
For %%L In ("Include:WhiteList:/I" "Exclude:BlackList:/V /I") Do For /F "tokens=1-3 delims=:" %%A In ("%%~L") Do (
If Not "!%%B!"=="" (
For %%W In (!%%B!) Do (Set %%A=!%%A! /C:"%%~W")
Set "%%A=|FindStr %%C!%%A!"
)
)
:: Построение массива
For /F "delims=" %%F In ('Dir "!BasePath!" /A-D /B /S!Include!!Exclude!') Do (
Set /A ArraySize+=1
Set "Array[!ArraySize!]=%%F"
)
If "!ArraySize!"=="0" Exit /B 1
Exit /B
:GetRandomElement
:: Если в массиве не осталось элементов, кидаем ошибку
If %ArraySize% LEQ 0 Exit /B 1
:: Инициализируем ГПСЧ и получаем номер случайного элемента массива
Echo !Random!!Random!>nul
Set /A Selected=1+%ArraySize%*!Random!/32768
Exit /B
:RebuildArray
:: Пересобираем массив со сдвигом значений, исключая из него выбранный элемент
Set Array[%Selected%]=
For /L %%E In (%Selected%,1,%ArraySize%) Do (
:: Проверка на конечный элемент массива
If "%Selected%"=="%ArraySize%" (
Set /A ArraySize-=1
Exit /B
)
Set /A Next=%%E+1
Call Set Array[%%E]=%%Array[!Next!]%%
)
Set /A ArraySize-=1
Exit /B
|