【问题标题】:Why the loop is not running as expected?为什么循环没有按预期运行?
【发布时间】:2015-10-26 19:30:28
【问题描述】:

我有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 ..
    )
)

【问题讨论】:

  • GOTO 破坏了 FOR 结构。
  • 感谢 Mofi 和 Squashman 的回复。 @Mofi Yesh 在我的代码中,从 for 到的所有内容都在一行上,就在我粘贴到此站点时,它拆分为多行。我是批处理编程的新手,很难像在 VBA 或其他与批处理中那样映射编码风格。我会尽量按照你的建议去做。谢谢。
  • @Mofi,不,从 fordo 的所有内容都不需要在同一行。
  • 有人可以帮我将代码拆分成所需的子程序,以便代码按预期工作吗?我正在阅读一些关于它的教程,因为我是这个批处理编程的新手。谢谢
  • 帮自己一个忙,改用真正的编程语言。这会更好地利用你的时间。

标签: batch-file goto delayedvariableexpansion


【解决方案1】:

代码主要有两个问题:

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

但是

  • goto 可以删除,如previous answer 中所示,
  • 不需要延迟扩展。不要将来自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 命令。

【讨论】:

    【解决方案2】:

    我不确定 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 :EOFexit /B,以避免在大多数外部for 循环完成后再次执行子例程的代码。这goto :EOF 导致退出该批处理文件的处理。

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

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

    【讨论】:

    • @MC ND 你太棒了! :) 再次解决了我的问题。感谢 Mofi 抽出时间。欣赏它。 MC ND 的代码对我有用并解决了我当前的问题。学习新事物。谢谢你们:)
    • @Mofi,你的代码也可以。谢谢大家的帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-01
    相关资源
    最近更新 更多