批处理 - 在for循环中设置变量

4

我目前正在尝试批量合并和重命名文件,但遇到了以下问题(这不是实际代码,而是演示问题的最小化示例):

@echo off
set /p "arg=Input the path to target directory (defaults to current directory if left empty): "

for %%f in ("%arg%\*.mkv") do (
  echo %%~nf
  set "out=%%~nf"
  echo %out%
)

pause

我的问题是这两个回声没有打印相同的值。第一个打印正确的内容(文件名),而第二个打印一些随机的东西,比如Echo is OFF或目录中的最后一个文件名。
经过一番搜索,我发现提到了使用延迟变量扩展(setlocal EnableDelayedExpansion)的方法,但这会引起一个问题,因为用户输入的目录路径可能包含惊叹号,如果我这样做,就会将它们删除(因此for循环根本不执行)。
我应该如何正确地设置for循环中的变量?
更新
在Dennis的解决方案和一些额外的试验和错误的帮助下,我终于能够修复原始代码,现在它可以正常工作了。对于任何感兴趣的人,这就是我的尝试目标:
for %%f in ("%arg%\*.mkv") do (
  set "n=%%~nf"

  setlocal EnableDelayedExpansion
  mkvmerge -o "!n:~15,10! !n:~25!" "!n!_Track00.h264" ...
  endlocal
)

实际命令要长得多,所以我没有完整粘贴它,只粘贴了足够证明需要的参数。我使用变量n,因为在延迟扩展环境中%%~nf不能很好地工作(即!s被删除),而且我不知道如何使用延迟扩展来取消引用双百分号变量(参数?)。
此外,尝试
set "out=%n:~15,10% %n:~25%"

在设置延迟扩展并运行之前

mkvmerge -o "!out!" ...

未正确延迟扩展,因此上面的代码就是我最终得到的代码。

你应该在for循环中使用!而不是%,所以echo !out!。我建议在这里查看:http://ss64.com/nt/delayedexpansion.html - Dennis van Gils
启用延迟扩展并在循环内使用 !。 - Dennis van Gils
1个回答

4

您应该尝试这个:

@echo off
set "arg=."
set /p "arg=Input the path to target directory (defaults to current directory if left empty): "
for %%f in ("%arg%\*.mkv") do (
  echo %%~nf
  set "out=%%~nf"
  setlocal EnableDelayedExpansion
  echo !out!
  endlocal
)
pause

我已经更新了问题。这会导致setlocal递归深度错误。 - Mate de Vita
编辑过了,你需要使用endlocal而不是setlocal disable。 - Dennis van Gils
好的,这个效果更好了,但仍然存在一个问题,因为它仍然会删除文件名中的感叹号(它们也可以包含感叹号)。有没有办法避免删除名称中所有问号? - Mate de Vita
修改后,这应该可以工作了。我还修复了“如果没有输入”的情况。 - Dennis van Gils
我已经成功将这个解决方案实现到我的代码中。我已经更新了我的问题并接受了这个答案。谢谢你的帮助。 - Mate de Vita
没问题,这让我的一天变得更美好了。 - Dennis van Gils

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接