Windows 调用另一个批处理时的批处理、for 循环和文件属性

Windows Batch, for loop and file attributes while calling another batch

我最近开始将我所有的视频文件转换为 MP4 以用于流式传输,并且到目前为止使用批处理没有问题。 现在我有 6000 多个视频要转换,需要某种我可以操作的队列系统。

这是我当前的代码,用于将目录中的所有内容转换为单独文件夹中的命令。

@echo off
setlocal disabledelayedexpansion
set dirs=D:\ANIME E:\ANIME F:\ANIME
for %%a in (%dirs%) do (
    echo %%a
    pushd %%a
    for /f "tokens=* delims= " %%f IN ('dir/b/s *.avi *.mkv *.m4v *.mpeg *.mpg') do (
        echo D:\handbrake\HandBrakeCLI.exe -i "%%f" -e qsv_h264 -q 20 -E fdk_haac -B 196 -R Auto -D 0,0,0,0 --audio-copy-mask aac,ac3,dtshd,dts,mp3 --audio-fallback copy:* --subtitle=1 --subtitle-default --subtitle-forced --subtitle-burn -o "%%~dpf%%~nf.mp4" > "D:\batch\%%~nf.bat"
        echo del /F "%%f" >> "D:\batch\%%~nf.bat"
    )
)

这很好用,让我可以调用 1000 个 bat 文件,这就是问题所在。 许多文件都有特殊字符,如 !在他们的名字中弄乱了我用来循环这些的 for 循环。我在处理之前将文件设置为只读,所以我的其他批次不会尝试转换同一个文件(我 运行 一次转换 3 个)。

我找到了使用 ENABLEDELAYEXPANSION 的解决方法,但在几次循环后我会收到错误消息,说我超出了最大调用次数。

@echo off
setlocal enableextensions 
echo Starting loop
goto loop

:loop
for  %%f in (D:\batch\*.bat) do (
    set ATTRIBS=%%~af
    setlocal enabledelayedexpansion
    set READ_ATTRIB=!ATTRIBS:~1,1!
    if !READ_ATTRIB!==- (
        setlocal disabledelayedexpansion
        attrib +R "%%f"
        call "%%f"
    )

    timeout /t 2 /nobreak
    goto loop
)
endlocal

通常你会说只要改变!变量到 % 并删除 delayedexpansion,但这让我在获取文件属性时出错。

set READ_ATTRIB=%ATTRIBS:~1,1%
        if %READ_ATTRIB%==- (

不会给我任何结果并且错误 ( 是意外的 如果我回显 READ_ATTRIB 结果总是 ~1,1 并且当回显其他人时我会得到 ECHO IS OFF.

有什么方法可以不使用 delayedexpansion 或者在几次循环后我不会出错?

32 is the deepest level of setlocal when used in batch file。您需要使用 setlocal - endlocal 对,类似于一对 ( 左括号和 ) 右括号。请参阅下面的大写 ENDLOCAL

@echo off
setlocal enableextensions 
echo Starting loop
goto loop

:loop
for  %%f in (D:\batch\*.bat) do (
    set ATTRIBS=%%~af
    setlocal enabledelayedexpansion
    set READ_ATTRIB=!ATTRIBS:~1,1!
    if !READ_ATTRIB!==- (
        setlocal disabledelayedexpansion
        attrib +R "%%f"
        call "%%f"
        ENDLOCAL
    )
    ENDLOCAL
    timeout /t 2 /nobreak
    REM                    this was totally mazy:  goto loop
)
endlocal

此外,您原始代码中的后者 goto loop 导致 for %%f 循环针对同一数据集无限期地初始化,即循环体中的 %%f 指的是一直只归档。见大写 REM.