多行批处理脚本转换为单行命令后返回的结果与原始命令不同

多行批处理脚本转换为单行命令后返回的结果与原始命令不同

我正在尝试转换多行脚本

@echo off

for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (
  pushd "%%D"
  for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul
  popd
  rd /s /q "%%D"
)
exit

将其添加到一行中,以便将其注册为上下文菜单项。据我理解,等效的单行命令如下:

@echo off && for /f "eol=: delims=" %%D in ('dir /b /s /ad *^|sort /r') do (pushd "%%D" && for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D") && exit

...但它产生的结果与原始脚本不同。

用 & 替换 && 会产生第三个不同的结果,但据我所知,在这种情况下我仍然需要 &&。

我可能做错了什么?

答案1

事实证明这for … do是“贪婪的”。(我不记得以前知道这一点,而且它似乎在 中没有突出的记录for /?。)

我的意思是:

考虑脚本cow1.bat

@echo off
for %%a in (how now brown) do echo %%a
echo cow

非常简单。运行时,它输出

how
now
brown
cow

正如我们所猜测的。

考虑脚本cow2.bat

@echo off
for %%a in (how now brown) do echo %%a & echo cow

相同,只是第 2 行和第 3 行已连接,并以 分隔&。猜猜是什么!?运行时,它会输出

how
cow
now
cow
brown
cow

它被解读为

@echo off
for %%a in (how now brown) do (echo %%a & echo cow)

(更改&&&没有任何效果。)令我更惊讶的是,

@echo off
for %%a in (how now brown) do (echo %%a) & echo cow

功能与 相同cow2。我不得不使用

@echo off
(for %%a in (how now brown) do echo %%a) & echo cow

获得原始的cow1行为。


这对 OP 有何影响?

for %%F in (*) do move "%%F" "..\%%~nxD - %%F" >nul && popd && rd /s /q "%%D"

类似于cow2:如果(我们刚刚进入的%%D目录)是,则上述代码段执行以下操作:pushdbeatles

move "george" "..\beatles - george" >nul    &&    popd    &&    rd /s /q "beatles"
move "john"   "..\beatles - john"   >nul    &&    popd    &&    rd /s /q "beatles"
move "paul"   "..\beatles - paul"   >nul    &&    popd    &&    rd /s /q "beatles"
move "ringo"  "..\beatles - ringo"  >nul    &&    popd    &&    rd /s /q "beatles"

(为清晰起见添加了空格)。因此,它会移动第一个文件(george),然后popd移出beatles目录并将其删除,而其他文件则由 roomba 来获取。

建议(TL;DR)

尝试

对于/f“eol =:delims =”%%D在('dir / b / s / ad * ^ | sort / r')中执行(pushd“%%D”&&对于 (*) 中的 %%F,请移动 "%%F" "..\%%~nxD - %%F" >nul&& popd && rd /s /q "%%D")
                                                                              ↑ ↑
 

琐碎问题:

为什么我们需要子命令*中的dir /b /s /ad *

相关内容