为什么循环不是预期的 运行?

Why the loop is not running as expected?

我有 E:\Backups\code\Hazard\test1 ... testn

这样的文件夹

在这些测试文件夹中,类似 E:\Backups\code\Hazard\test1\it0 ... itn

根文件夹是代码运行的地方 E:\Backups\code

以下代码在每个子文件夹上运行,并将 summary.ymlit0 文件夹复制到最新的 it(n) 文件夹。

为什么代码只为 test1 文件夹运行然后挂起?

setlocal ENABLEDELAYEDEXPANSION

set root=%cd%
for /D %%X in (%root%\*) do (
    echo %%X
    cd  %%X

    for /D /r %%b in (*) do ( 
        cd  %%b

        echo %%b

        for /f "tokens=1,2,*" %%a in ('robocopy . . file.txt /l /nocopy /is /s /nc /ns /ts /ndl /njh /njs ^| sort /r') do set "lastFolder=%%~dpc" & goto :done
:done
        echo Last folder : %lastFolder%

        for /d    %%j in (*) do  (
            if /i "%%~nj"=="it0" COPY %%j\summary.yml %lastFolder% 
        )
        cd ..
    )
)

我不确定带有 robocopy 的行应该做什么。看起来这个命令是为了获取当前目录中最后一个子目录的名称。

也许这段代码效果更好。但是我没法测试。

setlocal EnableDelayedExpansion
set "root=%cd%"

for /D %%X in ("%root%\*") do (
    echo %%X
    cd "%%~X"

    for /D /r %%b in (*) do (
        cd "%%~b"
        echo %%b

        call :GetLastFolder

        echo Last folder : !lastFolder!

        for /d %%j in (*) do (
            if /i "%%~nj"=="it0" copy "%%j\summary.yml" "!lastFolder!"
        )
        cd ..
    )
)
goto :EOF

:GetLastFolder
for /f "tokens=1,2,*" %%a in ('robocopy . . file.txt /l /nocopy /is /s /nc /ns /ts /ndl /njh /njs ^| sort /r') do set "lastFolder=%%~dpc" & goto :EOF
goto :EOF

至少需要用感叹号而不是百分号来引用环境变量lastFolder,才能真正根据需要在此处使用延迟扩展。

goto :EOF 退出子程序,导致在 call :GetLastFolder.

下面的行继续

在主代码之后还有一个goto :EOF或者exit /B,以避免子程序的代码在最外层for[=40=之后再次执行] 循环结束。这 goto :EOF 导致退出该批处理文件的处理。

要了解使用的命令及其工作原理,请打开命令提示符 window,至少执行以下命令,并仔细阅读每个命令显示的所有帮助页面。

  • call /?
  • for /?
  • goto /?
  • set /?

代码中主要有两个问题:

  • 如果在 for 循环中使用 goto,则循环被取消
  • 如果您在代码块(括号内的代码)内设置变量,要在同一代码块内检索变量的值,您需要延迟扩展,使用 setlocal enabledelayedexpansion 启用它并更改用于将变量中的值从 %var% 检索到 !var! 的语法。

但是

  • 可以删除 goto,如
  • 中所示
  • 不需要延迟扩展。不要将 for 可替换参数的值存储在变量中,只需使用可替换参数

未测试,但或多或​​少

@echo off
    setlocal enableextensions disabledelayedexpansion

    rem E:\Backups\ code   \  Hazard \ test1 \ it0 ... itn
    rem             ^root     ^ %%X    ^ %%Y           ^ %%~dpc

    for /D %%X in ("*") do for /D %%Y in ("%%~fX\*") do for /f "tokens=1,2,*" %%a in ('
        robocopy "%%~fY." "%%~fY." file.txt /l /nocopy /is /s /nc /ns /ts /ndl /njh /njs 
        ^| sort /r 2^>nul
        ^| cmd /q /v /c "(set /p .=&echo(!.!)"
    ') do copy "%%~fY\it0\summary.yml" "%%~dpc."

作为 E:\Backups\code 当前活动目录:

  • %%X 将枚举 E:\Backups\code (Hazard)
  • 下的文件夹
  • %%Y 将枚举 E:\Backups\code\Hazard (testn)
  • 下的文件夹
  • %%a 执行 robocopy 命令以定位包含最新 file.txt 文件的文件夹
  • sort /r 按降序对文件列表进行排序,因此最新的文件在列表中排在第一位
  • cmd 只检索并输出第一行
  • 利用几个 for 可替换参数中的所有可用信息,执行指示的 copy 命令。