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 /F
和 dir /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
对并更改 DisableDelayedExpansion
到 EnableDelayedExpansion
开头,这可能会稍微进一步提高性能,尽管很难注意到。
我正在使用个人使用的批处理文件生成 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 /F
和 dir /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
对并更改 DisableDelayedExpansion
到 EnableDelayedExpansion
开头,这可能会稍微进一步提高性能,尽管很难注意到。