Ибо l oop работает медленно, есть ли способ ускорить его в пакетном файле? - PullRequest
0 голосов
/ 21 июня 2020

Я генерирую html с помощью командного файла для личного использования, и в одном из моих разделов я получаю ширину и высоту всех файлов mp4 в папке. В этой "библиотеке mp4" файлы могут быть заменены, переименованы, добавлены или извлечены и т. Д. c ... поэтому я не хочу вручную вводить ширину и высоту каждый раз, когда она обновляется.

Этот код ниже работает, но он очень медленный ... есть ли способ ускорить его с помощью командного файла?

for /f %%g in ('dir /B /S *.mp4') do (

    set "g=%%g"
    set "g=!g:\=/!"
    
    for /f "tokens=1 delims=x" %%a in ('ffprobe -v error -select_streams v:0 -show_entries stream^=width^,height -of csv^=s^=x:p^=0 %%g') do set sW=%%a
    for /f "tokens=2 delims=x" %%b in ('ffprobe -v error -select_streams v:0 -show_entries stream^=width^,height -of csv^=s^=x:p^=0 %%g') do set sH=%%b
    
    echo %TAB% %TAB% ^<span^>^ ^<a style="text-decoration:none" class="image" href="file:///!g!" target="_blank"^>^ ^<video width="!sW!" height="!sH!" poster="file:///S:/_Stuff/_Data/_o/6.gif" poster="file:///S:/_Stuff/_Data/_o/6.gif" preload="auto" muted autoplay loop^>^ ^<source src="file:///!g!" type="video/mp4"^>^ ^</video^>^ ^</a^>^ ^</span^>^ >> _01.html 2>nul  
)

** ОБНОВЛЕНИЕ: Я пробовал это, и он работает, потребовалось 4 секунд против 11 секунд, но я только что заметил новый ответ, поэтому сейчас попробую это предложение!

@echo off
setlocal EnableDelayedExpansion

>_output_test.txt (for /f %%g in ('dir /B /S *.mp4') do (

    set "g=%%g"
    set "g=!g:\=/!"
    REM @echo !g!

    for /f "tokens=1,2 delims=x" %%a in ('ffprobe -v error -select_streams v:0 -show_entries stream^=width^,height -of csv^=s^=x:p^=0 %%g') do (
        set sW=%%a 
        set sH=%%b
    )
    REM @echo !sW!
    REM @echo !sH!
    @echo %TAB% %TAB% ^<span^>^ ^<a style="text-decoration:none" class="image" href="file:///!g!" target="_blank"^>^ ^<video width="!sW!" height="!sH!" poster="file:///S:/_DaveStuff/_Data/_o/6.gif" preload="auto" muted autoplay loop^>^ ^<source src="file:///!g!" type="video/mp4"^>^ ^</video^>^ ^</a^>^ ^</span^>^  
    )
)

endlocal
pause
exit

1 Ответ

1 голос
/ 21 июня 2020

Вы дважды выполняете одну и ту же ffprobe командную строку в отдельных for /F циклах, что, конечно, неэффективно. Более того, вы записываете каждую строку отдельно в выходной файл, поэтому происходит много отдельных операций ввода-вывода файла. Более того, for /F вместе с dir /B /S (который должен был быть dir /B /S /A:-D-H-S) сначала создают полный список элементов перед началом итерации, что здесь не требуется, поскольку повторяющиеся элементы не изменяются; поэтому a for /R l oop будет здесь быстрее, потому что он кэширует некоторые элементы и затем начинает выполнять итерацию.

Итак, вот возможное улучшение:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem // Redirect to the output files once only (`>` to overwrite, `>>` to append):
>> "_01.html" 2> nul (
    rem /* `for /F` + `dir /B /S` first retrieves the whole list of items before iterating,
    rem    but `for /R` begins to iterate earlier: */
    for /R %%F in (*.mp4) do (
        rem // Store currently iterated file path:
        set "FILE=%%F"
        rem // Get values from `ffprobe` program:
        for /F "tokens=1,2 delims=x" %%a in ('ffprobe -v error -select_streams v:0 -show_entries stream^=width^,height -of csv^=s^=x:p^=0 "%%F"') do set "sW=%%a" & set "sH=%%b"
        rem // Toggle delayed expansion to avoid troubles with `!`:
        setlocal EnableDelayedExpansion
        rem // Replace `\` by `/` in file path:
        set "FILE=!FILE:\=/!"
        rem // Return HTML string (with unnecessary escaping avoided):
        echo %TAB% %TAB% ^<span^> ^<a style="text-decoration:none" class="image" href="file:///!FILE!" target="_blank"^> ^<video width="!sW!" height="!sH!" poster="file:///S:/_Stuff/_Data/_o/6.gif" poster="file:///S:/_Stuff/_Data/_o/6.gif" preload="auto" muted autoplay loop^> ^<source src="file:///!FILE!" type="video/mp4"^> ^</video^> ^</a^> ^</span^> 
        endlocal
    )
)
endlocal

Если ни один из повторяющиеся пути к файлам содержат восклицательные знаки, вы можете удалить пару setlocal / endlocal внутри for /R l oop и изменить DisableDelayedExpansion на EnableDelayedExpansion в начале, что может немного улучшить производительность, хотя малозаметна.

...