2

I have folders like E:\Backups\code\Hazard\test1 ... testn

And inside these test folders something like E:\Backups\code\Hazard\test1\it0 ... itn

The root folder is E:\Backups\code from where the code runs.

The below code runs on each subfolders and copies summary.yml from it0 folder to latest it(n) folder.

Why the code runs just for test1 folder and then hangs?

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 ..
    )
)
aschipfl
  • 33,626
  • 12
  • 54
  • 99
bob
  • 71
  • 1
  • 1
  • 6
  • The GOTO breaks the FOR construct. – Squashman Oct 26 '15 at 19:38
  • Thanks Mofi and Squashman for your response. @ Mofi Yesh in my code everything from for to is on one line, its just when I pasted in this site it splits into multiple rows. I am new to batch programming and its hard to map the style of coding like in VBA or others vs in batch. I'll try to do as you have suggested. Thanks. – bob Oct 26 '15 at 19:43
  • @Mofi, no, everything from **for** to **do** does not need to be on the same line. – MC ND Oct 26 '15 at 20:13
  • Can someone please help me in splitting the code into required subroutine so that the code works as it is expected? I am going through some tutorials on it as I am new to this batch programming. Thanks – bob Oct 26 '15 at 20:23
  • Do yourself a favor and use a real programming language instead. It would be a much better use of your time. – nobody Oct 26 '15 at 22:33

2 Answers2

1

I'm not sure about what the line with robocopy should do. It looks like this command is for getting name of last subdirectory in current directory.

Perhaps this code works better. But I could not test it.

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

It is at least necessary to reference environment variable lastFolder with exclamation marks instead of percent signs to really use delayed expansion as needed here.

goto :EOF exits the subroutine resulting in continuing on line below call :GetLastFolder.

There is one more goto :EOF or alternatively exit /B after main code necessary to avoid that the code of the subroutine is executed once more after most outer for loop finished. This goto :EOF results in exiting the processing of this batch file.

For understanding the used commands and how they work, open a command prompt window, execute there at least the following commands, and read entirely all help pages displayed for each command very carefully.

  • call /?
  • for /?
  • goto /?
  • set /?
Mofi
  • 46,139
  • 17
  • 80
  • 143
  • @ MC ND you rock ! :) Solved my problem again. Thanks Mofi for giving your time. Appreciate it. MC ND's code works for me and solved my current problem. learning new things. Thanks ton you guys :) – bob Oct 26 '15 at 22:54
  • @ Mofi, you code also works. Thank you all for the help. – bob Oct 26 '15 at 22:58
1

There are two main problems in the code:

  • If goto is used inside a for loop, the loop is cancelled
  • If you set a variable inside a block of code (code inside parenthesis), to retrieve the value of the variable inside the same block of code you need delayed expansion, enabling it with setlocal enabledelayedexpansion and changing the syntax used to retrieve the value in the variable from %var% into !var!.

But

  • the goto can be removed as indicated in the previous answer,
  • the delayed expansion is not needed. Instead of storing the value from the for replaceable parameter inside a variable, just use the replaceable parameter

Not tested, but more or less

@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."

Being E:\Backups\code the current active directory:

  • %%X will enumerate the folders under E:\Backups\code (Hazard)
  • %%Y will enumerate the folders under E:\Backups\code\Hazard (testn)
  • %%a executes a robocopy command to locate the folder containing the latest file.txt file
  • sort /r sorts the list of files in descending order so the latest file is the first in the list
  • cmd retrieves and outputs only the first line
  • With all the information available in the several for replaceable parameters, execute the indicated copy command.
Community
  • 1
  • 1
MC ND
  • 69,615
  • 8
  • 84
  • 126