2015-10-26 2 views
2

У меня есть папки, такие как E:\Backups\code\Hazard\test1 ... testnПочему цикл работает не так, как ожидалось?

А внутри этих тестов папки что-то вроде E:\Backups\code\Hazard\test1\it0 ... itn

Корневая папка E:\Backups\code откуда запускается код.

Данный код работает на каждой подпапках и копиях summary.yml от it0 до последней версии 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 .. 
    ) 
) 
+0

GOTO разбивает конструкцию FOR. – Squashman

+0

Спасибо Mofi и Squashman за ваш ответ. @ Mofi Yesh в моем коде все от до для находится на одной строке, его просто, когда я вставил на этом сайте, он разбивается на несколько строк. Я новичок в пакетном программировании, и его трудно сопоставить стиль кодирования, как в VBA или других, а не в пакетном режиме. Я постараюсь сделать то, что вы предложили. Благодарю. – bob

+0

@Mofi, нет, все, от ** для ** до ** do **, не обязательно должно быть в одной строке. –

ответ

1

Есть две основные проблемы в коде:

  • Если goto используется внутри for цикл отменен
  • Если вы установите переменную внутри блока кода (код внутри скобки), чтобы получить значение переменной внутри одного и того же блока кода, вам потребуется отсроченное расширение, включив его с 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 команду.
1

Я не уверен, о том, что линия с 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 после того, как основной код необходимо избегать, что код подпрограммы выполняется еще раз после того, как самая внешняя для цикл завершен. Это goto :EOF приводит к завершению обработки этого командного файла.

Чтобы понять используемые команды и как они работают, откройте окно командной строки, выполните там, по крайней мере, следующие команды и внимательно прочитайте все страницы справки, отображаемые для каждой команды.

  • call /?
  • for /?
  • goto /?
  • set /?
+0

@ MC ND вы рок! :) Решила мою проблему снова. Спасибо Mofi за то, что уделили вам время. Ценить это. Код MC ND работает для меня и решил мою текущую проблему. изучая новые вещи. Спасибо, ты, ребята :) – bob

+0

@ Mofi, вы код тоже работает. Спасибо всем за помощь. – bob