You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

批处理For循环中输出PowerShell代码时的转义编码问题排查与解决

批处理For循环中输出PowerShell代码时的转义编码问题排查与解决

问题背景

最近我碰到个挺闹心的问题:把一段调用PowerShell做数值计算的批处理代码,整合到遍历文件的For循环里之后,代码突然卡住报错了。错误提示是[0] was unexpected at this time.,正好卡在输出PowerShell脚本内容的那一行。

我一开始试着用延迟扩展的!替换%来引用变量,比如把%MathType%改成!MathType!,但还是没解决问题,折腾了好一阵才找到关键所在。

问题根源

在批处理的For循环环境下,尤其是启用了延迟扩展后,[]这类符号会被批处理解释器当成自身的语法元素解析,而不是当作普通文本输出。当我们要把[int]$Calculation.split("...")[0]这类PowerShell代码写入文件时,批处理会错误地把[0]识别成自己的命令语法,从而触发报错。

解决方案

核心就是对]进行转义——在批处理里,用^符号来转义特殊字符。我们只需要在每个要输出的]前面加上^,就能让批处理把它当成普通文本处理,正确写入到PowerShell脚本文件中。

修改前的错误代码行:

ECHO [int]$Calculation.split("!MathType!")[0] !MathType! [int]$Calculation.split("!MathType!")[1] >> "!PSScript!"

修改后的正确代码行:

ECHO [int]$Calculation.split("!MathType!"^)[0] !MathType! [int]$Calculation.split("!MathType!"^)[1] >> "!PSScript!"

完整可运行脚本

这里附上我最终调试通过的完整脚本,它可以遍历指定文件列表里的视频文件,用ffmpeg转码压缩,还会自动计算压缩比率:

REM Change the console encoding to UTF-8 (for Nordic characters).
chcp 65001 | echo/

set filelist=%1

echo %filelist%

REM Define ESC escape character
for /f %%d in ('echo prompt $E ^| cmd') do (set "ESC=%%d")

REM Loop through all video files lists in a separate filelist
for /f "usebackq tokens=*" %%a in ("%filelist%") do (

call :StartTimer
set Bytes=%%~za

REM Below timestamp coding depends on locale setting on computer
set Timestamp=%%~ta
set TSYYYY=!Timestamp:~6,4!
set TSYY=!Timestamp:~8,2!
set TSMM=!Timestamp:~3,2!
set TSDD=!Timestamp:~0,2!
set TSHR=!Timestamp:~11,2!
set TSMIN=!Timestamp:~14,2!
set TSDato=!TSYY!!TSMM!!TSDD!
set TSTid=!TSHR!!TSMIN!

REM Display information about input file
echo !ESC![92;103mInputfile="%%~fa"!ESC![0m
echo !ESC![92;103mInputfile size=!Bytes! Bytes!ESC![0m

REM Convert to MP4 if needed, and compress to iPhone supported HEVC format
echo !ESC![91mConvert %%~xa file to MP4 format, and compress to iPhone supported HEVC format!ESC![0m
ffmpeg -n -hide_banner -loglevel quiet -i "%%~fa" -vcodec libx265 -vsync 0 -vtag hvc1 -crf 28 "%%~dpna_!TSDato!-!TSTid!.mp4"

REM Reset Console command after running ffmpeg
chcp 65001 | echo/

REM Find size of new file
FOR /F "tokens=*" %%b IN ("%%~dpna_!TSDato!-!TSTid!.mp4") DO set OutBytes=%%~zb

REM Find compression ratio new vs old file
SET "Calculation=!OutBytes!/!Bytes!"
SET "MathType=/"
SET PSScript=%temp%\PS~MathTemp.ps1

IF EXIST "!PSScript!" DEL /Q /F "!PSScript!"
ECHO $Calculation = "!Calculation!" > "!PSScript!"
ECHO [int]$Calculation.split("!MathType!"^)[0] !MathType! [int]$Calculation.split("!MathType!"^)[1] >> "!PSScript!"

FOR /F "USEBACKQ DELIMS=" %%c IN (`Powershell -ExecutionPolicy Bypass -Command "& '!PSScript!'"`) DO SET "Compression=%%c"

REM Display compression summary
echo !ESC![42mSummary!ESC![0m
echo !ESC![32mInputfile="%%~fa"!ESC![0m
echo !ESC![32mInputfile size=!Bytes! Bytes!ESC![0m
echo !ESC![32mOutputfile="%%~dpna_!TSDato!-!TSTid!.mp4"!ESC![0m
echo !ESC![32mOutputfile size=!OutBytes! Bytes!ESC![0m
echo !ESC![32mCompression rate=!Compression!!ESC![0m
echo !ESC![42mFile "%%~a" optimisation complete!ESC![0m

REM Clean up. If new file created, delete original file
if NOT exist "%%~dpna_!TSDato!-!TSTid!.mp4" (
echo !ESC![33mNo optimization has been performed!ESC![0m
) else (
del "%%~fa"
echo !ESC![47;91mOriginal file has been DELETED!ESC![0m
)

call :StopTimer
call :DisplayTimerResult

REM pause >nul
);=

echo. & echo All files optimised! & endlocal

REM Timer functions
:StartTimer
:: Store start time
set StartTIME=%TIME%
for /f "usebackq tokens=1-4 delims=:., " %%f in (`echo %StartTIME: =0%`) do set /a Start100S=1%%f*360000+1%%g*6000+1%%h*100+1%%i-36610100
goto :EOF

:StopTimer
:: Get the end time
set StopTIME=%TIME%
for /f "usebackq tokens=1-4 delims=:., " %%f in (`echo %StopTIME: =0%`) do set /a Stop100S=1%%f*360000+1%%g*6000+1%%h*100+1%%i-36610100
:: Test midnight rollover. If so, add 1 day=8640000 1/100ths secs
if %Stop100S% LSS %Start100S% set /a Stop100S+=8640000
set /a TookTime=%Stop100S%-%Start100S%
set TookTimePadded=0%TookTime%
goto :EOF

:DisplayTimerResult
:: Show timer start/stop/delta
echo Started: %StartTime%
echo Stopped: %StopTime%
echo Elapsed: %TookTime:~0,-2%.%TookTimePadded:~-2% seconds
goto :EOF

备注:内容来源于stack exchange,提问作者Fjorstut

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 06:27:59