我正在尝试编写一个命令程序,用于获取视频文件的高度并将其放入文件名中。我之前已经做过许多类似的命令程序,但这个命令程序给我带来了一个我从未见过的问题,而且现有的类似问题似乎没有解决这个问题。
基本命令流程看起来相当简单:
@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-28(Windows 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.命名文件时蝙蝠/命令/动态数据库/PS1和别的扩展, 确保不使用这相同的二进制文件名(例子:mediainfo.bat
和MediaInfo.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”那样进行评估。