批处理FOR命令异常:仅读取文本文件首行无法循环的问题排查
批处理脚本循环异常问题
问题详情
编写的批处理脚本中,外层循环仅执行一次,只读取mp4list-5.txt的第一行;但删除最后一条for /f "tokens=3" %%D in ('find/c "outro" %%A')命令后,循环就能正常遍历所有行。请问问题出在哪里?
完整脚本
@echo off setlocal enabledelayedexpansion <"mp4list-5.txt" ( for /F "delims=" %%A in (mp3list-5.txt) DO ( set /p mp4list= for /F "UseBackQ tokens=2 delims='" %%B in ("%%A") DO ( for /f %%C in ('Find /V /C "" ^< "%%A"') DO ( for /f "tokens=3" %%D in ('find/c "outro" %%A') do ( set "mp3list=%%A" set "outro=%%D" echo !mp4list! is MP4 list echo !mp3list! Is Mp3 List echo %%B is B echo %%~nB is FileName echo %%C is C echo %%D is How mnay times "outro" word exist if !outro! GEQ 1 ( set "exportname=%%~nB" ) if !outro! == 0 ( if %%C GEQ 2 ( set "exportname=!RANDOM!" ) ) if !outro! == 0 ( if %%C == 1 ( set "exportname=%%~nB" ) ) echo !exportname! REM Here the ffmpeg code will be to concatenate the mp3 and mp4 files, then join them. ) ) ) ) )
相关文件内容
mp4list-5.txt
F:\...\...\...\...\....\Videos-1\output-mp4.txt F:\...\...\...\...\....\Videos-2\output-mp4.txt F:\...\...\...\...\....\Videos-3\output-mp4.txt F:\...\...\...\...\....\Videos-4\output-mp4.txt
mp3list-5.txt
F:\...\...\...\...\....\Videos-1\output-mp3.txt F:\...\...\...\...\....\Videos-2\output-mp3.txt F:\...\...\...\...\....\Videos-3\output-mp3.txt F:\...\...\...\...\....\Videos-4\output-mp3.txt
问题原因与解决方法
核心原因
你用<"mp4list-5.txt"将文件关联到了控制台的标准输入(stdin),而for /f在执行子命令(比如find/c "outro" %%A)时,会默认占用并消耗stdin的剩余内容。第一次循环时,set /p读取了第一行,但后续的for /f子命令会把mp4list-5.txt剩下的所有行都当作自己的输入吃掉,导致后续循环里的set /p无法读取到内容,循环看似只执行了一次。
解决方法
方法1:阻止子命令占用主stdin
给执行find命令的for /f加上<nul,强制其不从主stdin读取内容:
for /f "tokens=3" %%D in ('find/c "outro" %%A ^<nul') do (
这样find命令就不会消耗mp4list-5.txt的剩余内容,set /p就能在每次循环里正常读取下一行。
方法2:改用数组存储mp4路径(更稳妥)
先把mp4list-5.txt的所有行存入数组,再和mp3list-5.txt的行一一对应遍历,彻底避免stdin共享冲突:
@echo off setlocal enabledelayedexpansion :: 先将mp4list-5.txt内容存入数组 set idx=0 for /F "delims=" %%M in (mp4list-5.txt) do ( set "mp4_arr[!idx!]=%%M" set /a idx+=1 ) :: 遍历mp3list,同时读取对应索引的mp4路径 set idx=0 for /F "delims=" %%A in (mp3list-5.txt) DO ( set "mp4list=!mp4_arr[!idx!]!" set /a idx+=1 :: 后续原有代码保持不变 for /F "UseBackQ tokens=2 delims='" %%B in ("%%A") DO ( for /f %%C in ('Find /V /C "" ^< "%%A"') DO ( for /f "tokens=3" %%D in ('find/c "outro" %%A') do ( set "mp3list=%%A" set "outro=%%D" echo !mp4list! is MP4 list echo !mp3list! Is Mp3 List echo %%B is B echo %%~nB is FileName echo %%C is C echo %%D is How mnay times "outro" word exist if !outro! GEQ 1 ( set "exportname=%%~nB" ) if !outro! == 0 ( if %%C GEQ 2 ( set "exportname=!RANDOM!" ) ) if !outro! == 0 ( if %%C == 1 ( set "exportname=%%~nB" ) ) echo !exportname! REM Here the ffmpeg code will be to concatenate the mp3 and mp4 files, then join them. ) ) ) )
内容的提问来源于stack exchange,提问作者Ionut Bejinariu
相关产品推荐
相关产品推荐

