Windows批处理文件在FOR循环中无法解释地重命名文件名

时间:2013-06-20 02:56:56

标签: windows cmd

Windows批处理文件在FOR循环

中无法解释地重命名文件名

我有一个小的Windows 7批处理文件来重命名MP3文件名库。我在这个问题中只包含了最后几行代码。它工作正常,除了代码部分的一个问题,该部分将变量的文本字符串(艺术家名称)附加到目录中的每个文件名。 (一旦解决,我的批处理文件将使用“set / p var =”来提示文本填充变量。)

此测试使用的两个示例文件名是:

01-serious song.mp3
02-happy song.mp3

此部分代码会导致问题:

@echo off
setlocal enabledelayedexpansion
::Temporay test variable
set str=Artist-
for %%a in (*.mp3) do (
  set oldName=%%a
  set newName=!str!!oldName!
  ren "!oldName!" "!newName!"
)
endlocal

结果是02文件以字符串附加一次(按预期)结束,而01文件名获取附加两次的字符串(错误):

Artist-Artist-01-serious song.mp3
Artist-02-happy song.mp3

我已经梳理了互联网,但没有找到关于这种情况的讨论。我不想说我自己花了大约8个小时来处理它。经过多次测试和研究,我认为重命名声明在某种程度上导致了这一点。

所以我改变了批处理文件,用其中的rename命令调用子程序,认为它干扰了for语句。那仍然有问题。然后我使用echo命令编辑批处理文件,如下所示进行测试。

第二版测试:

@echo off
setlocal enabledelayedexpansion
set str=Artist-
for %%a in (*.mp3) do (
set oldName=%%a
set newName=!str!!oldName!
  call :Action
echo.
echo back in For loop
)
echo.
echo For loop completed
echo !oldName!
echo !newName!
endlocal
goto:eof

:Action
echo.
echo start of Action loop
echo !oldName!
echo !newName!
ren "!oldName!" "!newName!"
echo end of Action loop

以下是CMD屏幕上显示的结果输出:

start of Action loop
01-serious song.mp3
Artist-01-serious song.mp3
end of Action loop

back in For loop

start of Action loop
02-happy song.mp3
Artist-02-happy song.mp3
end of Action loop

back in For loop

start of Action loop
Artist-01-serious song.mp3
Artist-Artist-01-serious song.mp3
end of Action loop

back in For loop

For loop completed
Artist-01-serious song.mp3
Artist-Artist-01-serious song.mp3

这很有趣,因为它显示正确调用子程序并返回两次。然后它以某种方式第三次被调用,它显然再次重命名01文件,第二次附加变量。

如果我在ren语句之前放置echo,那么屏幕输出显示子程序只被调用两次,但它当然不重命名文件。我也尝试使用move命令而不是重命名,并得到了相同的问题结果。

所以,我的问题是,为什么for循环调用子程序三次并使01文件被处理两次,我怎样才能让它按预期工作?

谢谢你,皮特。

2 个答案:

答案 0 :(得分:5)

尝试

for /f "delims=" %%a in (' dir /b /a-d *.mp3') do (

问题是您的原始语法找到了下一个文件名 - 它会找到您重命名的文件,因为新文件名(带前缀)逻辑上“大于”旧文件。

使用dir构建文件名列表,并在完成构建后处理列表 - 因此列表不会随着文件的重命名而变化。

"delims="子句确保文件名的默认解析无效 - 否则,文件名将被解释为一系列[空格分隔]标记。

答案 1 :(得分:2)

替换这个:

for %%a in (*.mp3) do (
  set oldName=%%a
  set newName=!str!!oldName!
  ren "!oldName!" "!newName!"
)

与此:

for /f "delims=" %%a in ('dir  /b /a-d *.mp3') do (
  set "oldName=%%~a"
  set "newName=%str%!oldName!"
  ren "!oldName!" "!newName!"
)

如果你愿意,我可以稍后解释一下,但彼得更快:)