Windows FOR 循环无法正确设置变量

Windows FOR 循环无法正确设置变量

我正在尝试编写一个命令程序,用于获取视频文件的高度并将其放入文件名中。我之前已经做过许多类似的命令程序,但这个命令程序给我带来了一个我从未见过的问题,而且现有的类似问题似乎没有解决这个问题。

基本命令流程看起来相当简单:

@echo off

FOR /F "tokens=*" %%G IN ('dir /b v*.mpg') DO (
     mediainfo.exe --Inform=Video;%%Height%% "%%G" > temporary.txt
     type temporary.txt
     set /p HeightVar=< temporary.txt 
     echo %HeightVar%
     REM RENAME "%%~nG" "%%~nG-%HeightVar%p%%~xG"
    )

我正在用一组三个文件测试这一点。第一个文件的高度为 684,其他文件的高度为 720。运行 mediainfo 并将高度值放入临时文件的命令有效。我可以查看该值,它会因每个文件而变化。其余命令似乎没问题,但是,当我运行该过程时,我看到了以下内容:

set "HeightVar="

set h
HOMEDRIVE=C:
HOMEPATH=\Users\user001

mediainfo.bat

FOR /F "tokens=*" %G IN ('dir /b v*.mpg') DO (
     mediainfo.exe --Inform=Video;%Height% "%G"  1>temporary.txt
     type temporary.txt
     set /p HeightVar=  0<temporary.txt
     echo 720
     REM RENAME "%~nG" "%~nG-720p%~xG"
    )
    
    (
     mediainfo.exe --Inform=Video;%Height% "Variety_2024-02-08_1601_Pass1.mpg"  1>temporary.txt
     type temporary.txt
     set /p HeightVar=  0<temporary.txt
     echo 720
     REM RENAME "Variety_2024-02-08_1601_Pass1" "Variety_2024-02-08_1601_Pass1-720p.mpg"
    )
    

我不明白为什么第一个“set /p HeightVar=< temporary.txt”会选取错误的值。您可以看到 temporary.txt 包含正确的值,但当运行该过程时,set 命令总是使用错误的值。

我已经尝试了能想到的所有 setlocal 和 endlocal 的组合(在循环内和循环外);我尝试了打开和关闭延迟扩展;我尝试了能想到的所有变量的组合;在运行该过程之前,我已经在命令提示符下清除了 HeightVar 的值,正如您从我在此处包含的输出中所看到的那样;并且我无法让循​​环为循环中读取的所有文件设置正确的值。

我愿意假设我忽略了一些“简单”错误,但我无论如何也找不到一个可行的组合。我编写了许多其他程序,这些程序遍历目录查找文件并处理文件或有关文件的信息,包括使用 MediaInfo,这是我做过的唯一一个不起作用的程序。

此时,我愿意接受任何有关如何解决该问题的建议。

答案1

@echo off 

cd /d "%~dp0"
>nul chcp 65001
set "_MediaInfo=C:\Program Files\MediaInfo\MediaInfo.exe"

for /f ^usebackq^delims^= %%G in =;(` "%__AppDir__%where.exe" .:v*.mpg `);= do for /f usebackq^delims^= %%i in =;(`
     call "%_MediaInfo%" --inform^^^=Video^^^;^^^%%Height^^^%% "%%~fG" `);= do rename "%%~fG" "%%~nG-%%~ip%%~xG"
            
>nul chcp 437

File.txt此任务无需使用附加功能,使用双For /f循环即可。


1. 媒体信息命令行界面安装并测试的版本:
MediaInfo.exe 版本 24.03,2024-03-28Windows Vista、7、8、10、11 23.03


附言:对于同时使用两个版本的人(图形用户界面命令行界面),我建议将二进制文件的 CLI 版本重命名为 MediaInfoCLI.exe,并相应地更改 _MediaInfo 变量的定义:

:: From
         set "_MediaInfo=C:\Program Files\MediaInfo<strong>MediaInfo.exe"
:: To
         set "_MediaInfo=C:\Program Files\MediaInfo<strong>MediaInfoCLI.exe"


2.考虑到MediaInfo.exe二进制(命令行)不在同一文件夹中,定义与MediaInfo.exe

  set "_MediaInfo=C:\Program Files\MediaInfo\MediaInfo.exe"

3.命名文件时///和别的, 确保不使用相同的二进制文件名(例子:mediainfo.batMediaInfo.exe),但要使用不同的名称,以确保你称呼你的运行,而不是你的或者相反,调用可执行文件和将根据变量中的值/顺序执行它%PathExt%

>Set PathExt
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW
>Echo/%PathExt%
.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.PY;.PYW

4.使用时UseBackQ在你的For /F循环,一定要更换'单引号`重音符在:

              

答案2

我找到了一个解决方法。我放弃了尝试让 set /p 工作。这个论坛中有几个从文本文件读取值的不同方法的示例,在我读到的第三篇文章中,我终于找到了一个真正有效的示例。我将其用于我的程序,并得到了以下结果:

SetLocal EnableDelayedExpansion

FOR /F "tokens=*" %%G IN ('dir /b v*.mpg') DO (
 mediainfo.exe --Inform=Video;%%Height%% "%%G" > temporary.txt
 type temporary.txt
 FOR /F "tokens=1" %%A in (temporary.txt) do (
    rename "%%G" "%%~nG_%%Ap%%~xG"
    )
)

在 FOR 循环内部,使用“tokens=1”且不使用“delim=”非常重要。我已经在三个目录中测试了它,到目前为止它都运行正常。但是,我想要处理的一些文件中有非标准字符。为了让它工作,我必须添加

65001

到批处理过程的开始,然后

437 号

最后。第一个命令会更改代码页,这样 Windows 就会接受扩展字符。第二个命令会重置回默认代码页。如果您不重置为默认代码页,那么像“more”这样的命令将在该命令窗口中失败。

我无法找到任何解释为什么“set /p”不能像“set”那样进行评估。

相关内容