For循环很慢,有什么办法可以在批处理文件中加快它的速度吗?

For loop is slow, any way to speed it up in a batch file?

我正在使用个人使用的批处理文件生成 html,我的其中一个部分正在获取一个文件夹中所有 mp4 文件的宽度和高度。这个“mp4 库”可以将文件换出、重命名、添加或提取等...所以我不想在每次更新时手动输入宽度和高度。

下面的代码有效,但速度很慢...有什么方法可以使用批处理文件使其更快吗?

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

您在单独的 for /F 循环中两次执行相同的 ffprobe 命令行,这当然是低效的。此外,您将每一行分别写入输出文件,因此会发生许多单独的文件 I/O 操作。此外,for /Fdir /B /S (应该是 dir /B /S /A:-D-H-S)在开始迭代之前首先构建完整的项目列表,这里不需要,因为迭代的项目没有改变;所以 for /R 循环在这里会更快,因为它缓存了一些项目然后开始迭代。

所以这是一个可能的改进:

@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

如果迭代文件路径中的 none 包含感叹号,您可以删除 for /R 循环中的 setlocal/endlocal 对并更改 DisableDelayedExpansionEnableDelayedExpansion 开头,这可能会稍微进一步提高性能,尽管很难注意到。